merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_post-orders-ORDER_ID-pay.c (164148B)


      1 /*
      2    This file is part of TALER
      3    (C) 2014-2026 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU Affero General Public License as
      7    published by the Free Software Foundation; either version 3,
      8    or (at your option) any later version.
      9 
     10    TALER is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public
     16    License along with TALER; see the file COPYING.  If not,
     17    see <http://www.gnu.org/licenses/>
     18  */
     19 
     20 /**
     21  * @file taler-merchant-httpd_post-orders-ORDER_ID-pay.c
     22  * @brief handling of POST /orders/$ID/pay requests
     23  * @author Marcello Stanisci
     24  * @author Christian Grothoff
     25  * @author Florian Dold
     26  */
     27 #include "taler/platform.h"
     28 #include <gnunet/gnunet_common.h>
     29 #include <gnunet/gnunet_db_lib.h>
     30 #include <gnunet/gnunet_json_lib.h>
     31 #include <gnunet/gnunet_time_lib.h>
     32 #include <jansson.h>
     33 #include <microhttpd.h>
     34 #include <stddef.h>
     35 #include <stdint.h>
     36 #include <string.h>
     37 #include <taler/taler_dbevents.h>
     38 #include <taler/taler_error_codes.h>
     39 #include <taler/taler_signatures.h>
     40 #include <taler/taler_json_lib.h>
     41 #include <taler/taler_exchange_service.h>
     42 #include "taler-merchant-httpd.h"
     43 #include "taler-merchant-httpd_exchanges.h"
     44 #include "taler-merchant-httpd_get-exchanges.h"
     45 #include "taler-merchant-httpd_helper.h"
     46 #include "taler-merchant-httpd_post-orders-ORDER_ID-pay.h"
     47 #include "taler-merchant-httpd_get-private-orders.h"
     48 #include "taler/taler_merchant_util.h"
     49 #include "taler/taler_merchantdb_plugin.h"
     50 
     51 #ifdef HAVE_DONAU_DONAU_SERVICE_H
     52 #include <donau/donau_service.h>
     53 #include <donau/donau_util.h>
     54 #include <donau/donau_json_lib.h>
     55 #endif
     56 
     57 /**
     58  * How often do we retry the (complex!) database transaction?
     59  */
     60 #define MAX_RETRIES 5
     61 
     62 /**
     63  * Maximum number of coins that we allow per transaction.
     64  * Note that the limit for each batch deposit request to
     65  * the exchange is lower, so we may break a very large
     66  * number of coins up into multiple smaller requests to
     67  * the exchange.
     68  */
     69 #define MAX_COIN_ALLOWED_COINS 1024
     70 
     71 /**
     72  * Maximum number of tokens that we allow as inputs per transaction
     73  */
     74 #define MAX_TOKEN_ALLOWED_INPUTS 64
     75 
     76 /**
     77  * Maximum number of tokens that we allow as outputs per transaction
     78  */
     79 #define MAX_TOKEN_ALLOWED_OUTPUTS 64
     80 
     81 /**
     82  * How often do we ask the exchange again about our
     83  * KYC status? Very rarely, as if the user actively
     84  * changes it, we should usually notice anyway.
     85  */
     86 #define KYC_RETRY_FREQUENCY GNUNET_TIME_UNIT_WEEKS
     87 
     88 /**
     89  * Information we keep for an individual call to the pay handler.
     90  */
     91 struct PayContext;
     92 
     93 
     94 /**
     95  * Different phases of processing the /pay request.
     96  */
     97 enum PayPhase
     98 {
     99   /**
    100    * Initial phase where the request is parsed.
    101    */
    102   PP_PARSE_PAY = 0,
    103 
    104   /**
    105    * Parse wallet data object from the pay request.
    106    */
    107   PP_PARSE_WALLET_DATA,
    108 
    109   /**
    110    * Check database state for the given order.
    111    */
    112   PP_CHECK_CONTRACT,
    113 
    114   /**
    115    * Validate provided tokens and token envelopes.
    116    */
    117   PP_VALIDATE_TOKENS,
    118 
    119   /**
    120    * Check if contract has been paid.
    121    */
    122   PP_CONTRACT_PAID,
    123 
    124   /**
    125    * Compute money pot changes.
    126    */
    127   PP_COMPUTE_MONEY_POTS,
    128 
    129   /**
    130    * Execute payment transaction.
    131    */
    132   PP_PAY_TRANSACTION,
    133 
    134   /**
    135    * Communicate with DONAU to generate a donation receipt from the donor BUDIs.
    136    */
    137   PP_REQUEST_DONATION_RECEIPT,
    138 
    139   /**
    140    * Process the donation receipt response from DONAU (save the donau_sigs to the db).
    141    */
    142   PP_FINAL_OUTPUT_TOKEN_PROCESSING,
    143 
    144   /**
    145    * Notify other processes about successful payment.
    146    */
    147   PP_PAYMENT_NOTIFICATION,
    148 
    149   /**
    150    * Create final success response.
    151    */
    152   PP_SUCCESS_RESPONSE,
    153 
    154   /**
    155    * Perform batch deposits with exchange(s).
    156    */
    157   PP_BATCH_DEPOSITS,
    158 
    159   /**
    160    * Return response in payment context.
    161    */
    162   PP_RETURN_RESPONSE,
    163 
    164   /**
    165    * An exchange denied a deposit, fail for
    166    * legal reasons.
    167    */
    168   PP_FAIL_LEGAL_REASONS,
    169 
    170   /**
    171    * Return #MHD_YES to end processing.
    172    */
    173   PP_END_YES,
    174 
    175   /**
    176    * Return #MHD_NO to end processing.
    177    */
    178   PP_END_NO
    179 };
    180 
    181 
    182 /**
    183  * Information kept during a pay request for each coin.
    184  */
    185 struct DepositConfirmation
    186 {
    187 
    188   /**
    189    * Reference to the main PayContext
    190    */
    191   struct PayContext *pc;
    192 
    193   /**
    194    * URL of the exchange that issued this coin.
    195    */
    196   char *exchange_url;
    197 
    198   /**
    199    * Details about the coin being deposited.
    200    */
    201   struct TALER_EXCHANGE_CoinDepositDetail cdd;
    202 
    203   /**
    204    * Fee charged by the exchange for the deposit operation of this coin.
    205    */
    206   struct TALER_Amount deposit_fee;
    207 
    208   /**
    209    * Fee charged by the exchange for the refund operation of this coin.
    210    */
    211   struct TALER_Amount refund_fee;
    212 
    213   /**
    214    * If a minimum age was required (i. e. pc->minimum_age is large enough),
    215    * this is the signature of the minimum age (as a single uint8_t), using the
    216    * private key to the corresponding age group.  Might be all zeroes for no
    217    * age attestation.
    218    */
    219   struct TALER_AgeAttestationP minimum_age_sig;
    220 
    221   /**
    222    * If a minimum age was required (i. e. pc->minimum_age is large enough),
    223    * this is the age commitment (i. e. age mask and vector of EdDSA public
    224    * keys, one per age group) that went into the mining of the coin.  The
    225    * SHA256 hash of the mask and the vector of public keys was bound to the
    226    * key.
    227    */
    228   struct TALER_AgeCommitment age_commitment;
    229 
    230   /**
    231    * Age mask in the denomination that defines the age groups.  Only
    232    * applicable, if minimum age was required.
    233    */
    234   struct TALER_AgeMask age_mask;
    235 
    236   /**
    237    * Offset of this coin into the `dc` array of all coins in the
    238    * @e pc.
    239    */
    240   unsigned int index;
    241 
    242   /**
    243    * true, if no field "age_commitment" was found in the JSON blob
    244    */
    245   bool no_age_commitment;
    246 
    247   /**
    248    * True, if no field "minimum_age_sig" was found in the JSON blob
    249    */
    250   bool no_minimum_age_sig;
    251 
    252   /**
    253    * true, if no field "h_age_commitment" was found in the JSON blob
    254    */
    255   bool no_h_age_commitment;
    256 
    257   /**
    258    * true if we found this coin in the database.
    259    */
    260   bool found_in_db;
    261 
    262   /**
    263    * true if we #deposit_paid_check() matched this coin in the database.
    264    */
    265   bool matched_in_db;
    266 
    267   /**
    268    * True if this coin is in the current batch.
    269    */
    270   bool in_batch;
    271 
    272 };
    273 
    274 struct TokenUseConfirmation
    275 {
    276 
    277   /**
    278    * Signature on the deposit request made using the token use private key.
    279    */
    280   struct TALER_TokenUseSignatureP sig;
    281 
    282   /**
    283    * Token use public key. This key was blindly signed by the merchant during
    284    * the token issuance process.
    285    */
    286   struct TALER_TokenUsePublicKeyP pub;
    287 
    288   /**
    289    * Unblinded signature on the token use public key done by the merchant.
    290    */
    291   struct TALER_TokenIssueSignature unblinded_sig;
    292 
    293   /**
    294    * Hash of the token issue public key associated with this token.
    295    * Note this is set in the validate_tokens phase.
    296    */
    297   struct TALER_TokenIssuePublicKeyHashP h_issue;
    298 
    299   /**
    300    * true if we found this token in the database.
    301    */
    302   bool found_in_db;
    303 
    304 };
    305 
    306 
    307 /**
    308  * Information about a token envelope.
    309  */
    310 struct TokenEnvelope
    311 {
    312 
    313   /**
    314    * Blinded token use public keys waiting to be signed.
    315    */
    316   struct TALER_TokenEnvelope blinded_token;
    317 
    318 };
    319 
    320 
    321 /**
    322  * (Blindly) signed token to be returned to the wallet.
    323  */
    324 struct SignedOutputToken
    325 {
    326 
    327   /**
    328    * Index of the output token that produced
    329    * this blindly signed token.
    330    */
    331   unsigned int output_index;
    332 
    333   /**
    334    * Blinded token use public keys waiting to be signed.
    335    */
    336   struct TALER_BlindedTokenIssueSignature sig;
    337 
    338   /**
    339    * Hash of token issue public key.
    340    */
    341   struct TALER_TokenIssuePublicKeyHashP h_issue;
    342 
    343 };
    344 
    345 
    346 /**
    347  * Information kept during a pay request for each exchange.
    348  */
    349 struct ExchangeGroup
    350 {
    351 
    352   /**
    353    * Payment context this group is part of.
    354    */
    355   struct PayContext *pc;
    356 
    357   /**
    358    * Handle to the batch deposit operation currently in flight for this
    359    * exchange, NULL when no operation is pending.
    360    */
    361   struct TALER_EXCHANGE_PostBatchDepositHandle *bdh;
    362 
    363   /**
    364    * Handle for operation to lookup /keys (and auditors) from
    365    * the exchange used for this transaction; NULL if no operation is
    366    * pending.
    367    */
    368   struct TMH_EXCHANGES_KeysOperation *fo;
    369 
    370   /**
    371    * URL of the exchange that issued this coin. Aliases
    372    * the exchange URL of one of the coins, do not free!
    373    */
    374   const char *exchange_url;
    375 
    376   /**
    377    * The keys of the exchange.
    378    */
    379   struct TALER_EXCHANGE_Keys *keys;
    380 
    381   /**
    382    * Total deposit amount in this exchange group.
    383    */
    384   struct TALER_Amount total;
    385 
    386   /**
    387    * Wire fee that applies to this exchange for the
    388    * given payment context's wire method.
    389    */
    390   struct TALER_Amount wire_fee;
    391 
    392   /**
    393    * true if we already tried a forced /keys download.
    394    */
    395   bool tried_force_keys;
    396 
    397   /**
    398    * Did this exchange deny the transaction for legal reasons?
    399    */
    400   bool got_451;
    401 };
    402 
    403 
    404 /**
    405  * Information about donau, that can be fetched even
    406  * if the merhchant doesn't support donau
    407  */
    408 struct DonauData
    409 {
    410   /**
    411    * The user-selected Donau URL.
    412    */
    413   char *donau_url;
    414 
    415   /**
    416    * The donation year, as parsed from "year".
    417    */
    418   uint64_t donation_year;
    419 
    420   /**
    421    * The original BUDI key-pairs array from the donor
    422    * to be used for the receipt creation.
    423    */
    424   const json_t *budikeypairs;
    425 };
    426 
    427 /**
    428  * Information we keep for an individual call to the /pay handler.
    429  */
    430 struct PayContext
    431 {
    432 
    433   /**
    434    * Stored in a DLL.
    435    */
    436   struct PayContext *next;
    437 
    438   /**
    439    * Stored in a DLL.
    440    */
    441   struct PayContext *prev;
    442 
    443   /**
    444    * MHD connection to return to
    445    */
    446   struct MHD_Connection *connection;
    447 
    448   /**
    449    * Details about the client's request.
    450    */
    451   struct TMH_HandlerContext *hc;
    452 
    453   /**
    454    * Transaction ID given in @e root.
    455    */
    456   const char *order_id;
    457 
    458   /**
    459    * Response to return, NULL if we don't have one yet.
    460    */
    461   struct MHD_Response *response;
    462 
    463   /**
    464    * Array with @e output_tokens_len signed tokens returned in
    465    * the response to the wallet.
    466    */
    467   struct SignedOutputToken *output_tokens;
    468 
    469   /**
    470    * Number of output tokens to return in the response.
    471    * Length of the @e output_tokens array.
    472    */
    473   unsigned int output_tokens_len;
    474 
    475   /**
    476    * Counter used to generate the output index in append_output_token_sig().
    477    */
    478   unsigned int output_index_gen;
    479 
    480   /**
    481    * Counter used to generate the output index in append_output_token_sig().
    482    *
    483    * Counts the generated tokens _within_ the current output_index_gen.
    484    */
    485   unsigned int output_token_cnt;
    486 
    487   /**
    488    * HTTP status code to use for the reply, i.e 200 for "OK".
    489    * Special value UINT_MAX is used to indicate hard errors
    490    * (no reply, return #MHD_NO).
    491    */
    492   unsigned int response_code;
    493 
    494   /**
    495    * Payment processing phase we are in.
    496    */
    497   enum PayPhase phase;
    498 
    499   /**
    500    * #GNUNET_NO if the @e connection was not suspended,
    501    * #GNUNET_YES if the @e connection was suspended,
    502    * #GNUNET_SYSERR if @e connection was resumed to as
    503    * part of #MH_force_pc_resume during shutdown.
    504    */
    505   enum GNUNET_GenericReturnValue suspended;
    506 
    507   /**
    508    * Results from the phase_parse_pay()
    509    */
    510   struct
    511   {
    512 
    513     /**
    514      * Array with @e num_exchanges exchanges we are depositing
    515      * coins into.
    516      */
    517     struct ExchangeGroup **egs;
    518 
    519     /**
    520      * Array with @e coins_cnt coins we are despositing.
    521      */
    522     struct DepositConfirmation *dc;
    523 
    524     /**
    525      * Array with @e tokens_cnt input tokens passed to this request.
    526      */
    527     struct TokenUseConfirmation *tokens;
    528 
    529     /**
    530      * Optional session id given in @e root.
    531      * NULL if not given.
    532      */
    533     char *session_id;
    534 
    535     /**
    536      * Wallet data json object from the request. Containing additional
    537      * wallet data such as the selected choice_index.
    538      */
    539     const json_t *wallet_data;
    540 
    541     /**
    542      * Number of coins this payment is made of.  Length
    543      * of the @e dc array.
    544      */
    545     size_t coins_cnt;
    546 
    547     /**
    548      * Number of input tokens passed to this request.  Length
    549      * of the @e tokens array.
    550      */
    551     size_t tokens_cnt;
    552 
    553     /**
    554      * Number of exchanges involved in the payment. Length
    555      * of the @e eg array.
    556      */
    557     unsigned int num_exchanges;
    558 
    559   } parse_pay;
    560 
    561   /**
    562    * Results from the phase_wallet_data()
    563    */
    564   struct
    565   {
    566 
    567     /**
    568      * Array with @e token_envelopes_cnt (blinded) token envelopes.
    569      */
    570     struct TokenEnvelope *token_envelopes;
    571 
    572     /**
    573      * Index of selected choice in the @e contract_terms choices array.
    574      */
    575     int16_t choice_index;
    576 
    577     /**
    578      * Number of token envelopes passed to this request.
    579      * Length of the @e token_envelopes array.
    580      */
    581     size_t token_envelopes_cnt;
    582 
    583     /**
    584      * Hash of the canonicalized wallet data json object.
    585      */
    586     struct GNUNET_HashCode h_wallet_data;
    587 
    588     /**
    589      * Donau related information
    590      */
    591     struct DonauData donau;
    592 
    593     /**
    594      * Serial from the DB of the donau instance that we are using
    595      */
    596     uint64_t donau_instance_serial;
    597 
    598 #ifdef  HAVE_DONAU_DONAU_SERVICE_H
    599     /**
    600      * Number of the blinded key pairs @e bkps
    601      */
    602     unsigned int num_bkps;
    603 
    604     /**
    605      * Blinded key pairs received from the wallet
    606      */
    607     struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps;
    608 
    609     /**
    610      * The id of the charity as saved on the donau.
    611      */
    612     uint64_t charity_id;
    613 
    614     /**
    615      * Private key of the charity(related to the private key of the merchant).
    616      */
    617     struct DONAU_CharityPrivateKeyP charity_priv;
    618 
    619     /**
    620      * Maximum amount of donations that the charity can receive per year.
    621      */
    622     struct TALER_Amount charity_max_per_year;
    623 
    624     /**
    625      * Amount of donations that the charity has received so far this year.
    626      */
    627     struct TALER_Amount charity_receipts_to_date;
    628 
    629     /**
    630      * Donau keys, that we are using to get the information about the bkps.
    631      */
    632     struct DONAU_Keys *donau_keys;
    633 
    634     /**
    635      * Amount from BKPS
    636      */
    637     struct TALER_Amount donation_amount;
    638 #endif
    639 
    640   } parse_wallet_data;
    641 
    642   /**
    643    * Results from the phase_check_contract()
    644    */
    645   struct
    646   {
    647 
    648     /**
    649      * Hashed @e contract_terms.
    650      */
    651     struct TALER_PrivateContractHashP h_contract_terms;
    652 
    653     /**
    654      * Our contract (or NULL if not available).
    655      */
    656     json_t *contract_terms_json;
    657 
    658     /**
    659      * Parsed contract terms, NULL when parsing failed.
    660      */
    661     struct TALER_MERCHANT_Contract *contract_terms;
    662 
    663     /**
    664      * What wire method (of the @e mi) was selected by the wallet?
    665      * Set in #phase_parse_pay().
    666      */
    667     struct TMH_WireMethod *wm;
    668 
    669     /**
    670      * Set to the POS key, if applicable for this order.
    671      */
    672     char *pos_key;
    673 
    674     /**
    675      * Serial number of this order in the database (set once we did the lookup).
    676      */
    677     uint64_t order_serial;
    678 
    679     /**
    680      * Algorithm chosen for generating the confirmation code.
    681      */
    682     enum TALER_MerchantConfirmationAlgorithm pos_alg;
    683 
    684   } check_contract;
    685 
    686   /**
    687    * Results from the phase_validate_tokens()
    688    */
    689   struct
    690   {
    691 
    692     /**
    693      * Maximum fee the merchant is willing to pay, from @e root.
    694      * Note that IF the total fee of the exchange is higher, that is
    695      * acceptable to the merchant if the customer is willing to
    696      * pay the difference
    697      * (i.e. amount - max_fee <= actual_amount - actual_fee).
    698      */
    699     struct TALER_Amount max_fee;
    700 
    701     /**
    702      * Amount from @e root.  This is the amount the merchant expects
    703      * to make, minus @e max_fee.
    704      */
    705     struct TALER_Amount brutto;
    706 
    707     /**
    708      * Index of the donau output in the list of tokens.
    709      * Set to -1 if no donau output exists.
    710      */
    711     int donau_output_index;
    712 
    713   } validate_tokens;
    714 
    715 
    716   struct
    717   {
    718     /**
    719      * Length of the @a pots and @a increments arrays.
    720      */
    721     unsigned int num_pots;
    722 
    723     /**
    724      * Serial IDs of money pots to increment.
    725      */
    726     uint64_t *pots;
    727 
    728     /**
    729      * Increment for the respective money pot.
    730      */
    731     struct TALER_Amount *increments;
    732 
    733     /**
    734      * True if the money pots have already been computed.
    735      */
    736     bool pots_computed;
    737 
    738   } compute_money_pots;
    739 
    740   /**
    741    * Results from the phase_execute_pay_transaction()
    742    */
    743   struct
    744   {
    745 
    746     /**
    747      * Considering all the coins with the "found_in_db" flag
    748      * set, what is the total amount we were so far paid on
    749      * this contract?
    750      */
    751     struct TALER_Amount total_paid;
    752 
    753     /**
    754      * Considering all the coins with the "found_in_db" flag
    755      * set, what is the total amount we had to pay in deposit
    756      * fees so far on this contract?
    757      */
    758     struct TALER_Amount total_fees_paid;
    759 
    760     /**
    761      * Considering all the coins with the "found_in_db" flag
    762      * set, what is the total amount we already refunded?
    763      */
    764     struct TALER_Amount total_refunded;
    765 
    766     /**
    767      * Number of coin deposits pending.
    768      */
    769     unsigned int pending;
    770 
    771     /**
    772      * How often have we retried the 'main' transaction?
    773      */
    774     unsigned int retry_counter;
    775 
    776     /**
    777      * Set to true if the deposit currency of a coin
    778      * does not match the contract currency.
    779      */
    780     bool deposit_currency_mismatch;
    781 
    782     /**
    783      * Set to true if the database contains a (bogus)
    784      * refund for a different currency.
    785      */
    786     bool refund_currency_mismatch;
    787 
    788   } pay_transaction;
    789 
    790   /**
    791    * Results from the phase_batch_deposits()
    792    */
    793   struct
    794   {
    795 
    796     /**
    797      * Task called when the (suspended) processing for
    798      * the /pay request times out.
    799      * Happens when we don't get a response from the exchange.
    800      */
    801     struct GNUNET_SCHEDULER_Task *timeout_task;
    802 
    803     /**
    804      * Number of batch transactions pending.
    805      */
    806     unsigned int pending_at_eg;
    807 
    808     /**
    809      * Did any exchange deny a deposit for legal reasons?
    810      */
    811     bool got_451;
    812 
    813   } batch_deposits;
    814 
    815 #ifdef HAVE_DONAU_DONAU_SERVICE_H
    816   /**
    817    * Struct for #phase_request_donation_receipt()
    818    */
    819   struct
    820   {
    821     /**
    822      * Handler of the donau request
    823      */
    824     struct DONAU_BatchIssueReceiptHandle *birh;
    825 
    826   } donau_receipt;
    827 #endif
    828 };
    829 
    830 
    831 /**
    832  * Head of active pay context DLL.
    833  */
    834 static struct PayContext *pc_head;
    835 
    836 /**
    837  * Tail of active pay context DLL.
    838  */
    839 static struct PayContext *pc_tail;
    840 
    841 
    842 void
    843 TMH_force_pc_resume ()
    844 {
    845   for (struct PayContext *pc = pc_head;
    846        NULL != pc;
    847        pc = pc->next)
    848   {
    849     if (NULL != pc->batch_deposits.timeout_task)
    850     {
    851       GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
    852       pc->batch_deposits.timeout_task = NULL;
    853     }
    854     if (GNUNET_YES == pc->suspended)
    855     {
    856       pc->suspended = GNUNET_SYSERR;
    857       MHD_resume_connection (pc->connection);
    858     }
    859   }
    860 }
    861 
    862 
    863 /**
    864  * Resume payment processing.
    865  *
    866  * @param[in,out] pc payment process to resume
    867  */
    868 static void
    869 pay_resume (struct PayContext *pc)
    870 {
    871   GNUNET_assert (GNUNET_YES == pc->suspended);
    872   pc->suspended = GNUNET_NO;
    873   MHD_resume_connection (pc->connection);
    874   TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
    875 }
    876 
    877 
    878 /**
    879  * Resume the given pay context and send the given response.
    880  * Stores the response in the @a pc and signals MHD to resume
    881  * the connection.  Also ensures MHD runs immediately.
    882  *
    883  * @param pc payment context
    884  * @param response_code response code to use
    885  * @param response response data to send back
    886  */
    887 static void
    888 resume_pay_with_response (struct PayContext *pc,
    889                           unsigned int response_code,
    890                           struct MHD_Response *response)
    891 {
    892   pc->response_code = response_code;
    893   pc->response = response;
    894   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    895               "Resuming /pay handling. HTTP status for our reply is %u.\n",
    896               response_code);
    897   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
    898   {
    899     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
    900 
    901     if (NULL != eg->fo)
    902     {
    903       TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
    904       eg->fo = NULL;
    905       pc->batch_deposits.pending_at_eg--;
    906     }
    907     if (NULL != eg->bdh)
    908     {
    909       TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh);
    910       eg->bdh = NULL;
    911       pc->batch_deposits.pending_at_eg--;
    912     }
    913   }
    914   GNUNET_assert (0 == pc->batch_deposits.pending_at_eg);
    915   if (NULL != pc->batch_deposits.timeout_task)
    916   {
    917     GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
    918     pc->batch_deposits.timeout_task = NULL;
    919   }
    920   pc->phase = PP_RETURN_RESPONSE;
    921   pay_resume (pc);
    922 }
    923 
    924 
    925 /**
    926  * Resume payment processing with an error.
    927  *
    928  * @param pc operation to resume
    929  * @param ec taler error code to return
    930  * @param msg human readable error message
    931  */
    932 static void
    933 resume_pay_with_error (struct PayContext *pc,
    934                        enum TALER_ErrorCode ec,
    935                        const char *msg)
    936 {
    937   resume_pay_with_response (
    938     pc,
    939     TALER_ErrorCode_get_http_status_safe (ec),
    940     TALER_MHD_make_error (ec,
    941                           msg));
    942 }
    943 
    944 
    945 /**
    946  * Conclude payment processing for @a pc with the
    947  * given @a res MHD status code.
    948  *
    949  * @param[in,out] pc payment context for final state transition
    950  * @param res MHD return code to end with
    951  */
    952 static void
    953 pay_end (struct PayContext *pc,
    954          MHD_RESULT res)
    955 {
    956   pc->phase = (MHD_YES == res)
    957     ? PP_END_YES
    958     : PP_END_NO;
    959 }
    960 
    961 
    962 /**
    963  * Return response stored in @a pc.
    964  *
    965  * @param[in,out] pc payment context we are processing
    966  */
    967 static void
    968 phase_return_response (struct PayContext *pc)
    969 {
    970   GNUNET_assert (0 != pc->response_code);
    971   /* We are *done* processing the request, just queue the response (!) */
    972   if (UINT_MAX == pc->response_code)
    973   {
    974     GNUNET_break (0);
    975     pay_end (pc,
    976              MHD_NO); /* hard error */
    977     return;
    978   }
    979   pay_end (pc,
    980            MHD_queue_response (pc->connection,
    981                                pc->response_code,
    982                                pc->response));
    983 }
    984 
    985 
    986 /**
    987  * Return a response indicating failure for legal reasons.
    988  *
    989  * @param[in,out] pc payment context we are processing
    990  */
    991 static void
    992 phase_fail_for_legal_reasons (struct PayContext *pc)
    993 {
    994   json_t *exchanges;
    995 
    996   GNUNET_assert (0 == pc->pay_transaction.pending);
    997   GNUNET_assert (pc->batch_deposits.got_451);
    998   exchanges = json_array ();
    999   GNUNET_assert (NULL != exchanges);
   1000   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   1001   {
   1002     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   1003 
   1004     GNUNET_assert (NULL == eg->fo);
   1005     GNUNET_assert (NULL == eg->bdh);
   1006     if (! eg->got_451)
   1007       continue;
   1008     GNUNET_assert (
   1009       0 ==
   1010       json_array_append_new (
   1011         exchanges,
   1012         json_string (eg->exchange_url)));
   1013   }
   1014   pay_end (pc,
   1015            TALER_MHD_REPLY_JSON_PACK (
   1016              pc->connection,
   1017              MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
   1018              TALER_JSON_pack_ec (
   1019                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED),
   1020              GNUNET_JSON_pack_array_steal ("exchange_base_urls",
   1021                                            exchanges)));
   1022 }
   1023 
   1024 
   1025 /**
   1026  * Do database transaction for a completed batch deposit.
   1027  *
   1028  * @param eg group that completed
   1029  * @param dr response from the server
   1030  * @return transaction status
   1031  */
   1032 static enum GNUNET_DB_QueryStatus
   1033 batch_deposit_transaction (
   1034   const struct ExchangeGroup *eg,
   1035   const struct TALER_EXCHANGE_PostBatchDepositResponse *dr)
   1036 {
   1037   const struct PayContext *pc = eg->pc;
   1038   enum GNUNET_DB_QueryStatus qs;
   1039   uint64_t b_dep_serial;
   1040   uint32_t off = 0;
   1041 
   1042   qs = TMH_db->insert_deposit_confirmation (
   1043     TMH_db->cls,
   1044     pc->hc->instance->settings.id,
   1045     dr->details.ok.deposit_timestamp,
   1046     &pc->check_contract.h_contract_terms,
   1047     eg->exchange_url,
   1048     pc->check_contract.contract_terms->wire_deadline,
   1049     &dr->details.ok.accumulated_total_without_fee,
   1050     &eg->wire_fee,
   1051     &pc->check_contract.wm->h_wire,
   1052     dr->details.ok.exchange_sig,
   1053     dr->details.ok.exchange_pub,
   1054     &b_dep_serial);
   1055   if (qs <= 0)
   1056     return qs; /* Entire batch already known or failure, we're done */
   1057 
   1058   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1059   {
   1060     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1061 
   1062     /* might want to group deposits by batch more explicitly ... */
   1063     if (0 != strcmp (eg->exchange_url,
   1064                      dc->exchange_url))
   1065       continue;
   1066     if (dc->found_in_db)
   1067       continue;
   1068     if (! dc->in_batch)
   1069       continue;
   1070     /* FIXME-#9457: We might want to check if the order was fully paid concurrently
   1071        by some other wallet here, and if so, issue an auto-refund. Right now,
   1072        it is possible to over-pay if two wallets literally make a concurrent
   1073        payment, as the earlier check for 'paid' is not in the same transaction
   1074        scope as this 'insert' operation. */
   1075     qs = TMH_db->insert_deposit (
   1076       TMH_db->cls,
   1077       off++, /* might want to group deposits by batch more explicitly ... */
   1078       b_dep_serial,
   1079       &dc->cdd.coin_pub,
   1080       &dc->cdd.coin_sig,
   1081       &dc->cdd.amount,
   1082       &dc->deposit_fee,
   1083       &dc->refund_fee,
   1084       GNUNET_TIME_absolute_add (
   1085         pc->check_contract.contract_terms->wire_deadline.abs_time,
   1086         GNUNET_TIME_randomize (GNUNET_TIME_UNIT_MINUTES)));
   1087     if (qs < 0)
   1088       return qs;
   1089     GNUNET_break (qs > 0);
   1090   }
   1091   return qs;
   1092 }
   1093 
   1094 
   1095 /**
   1096  * Handle case where the batch deposit completed
   1097  * with a status of #MHD_HTTP_OK.
   1098  *
   1099  * @param eg group that completed
   1100  * @param dr response from the server
   1101  */
   1102 static void
   1103 handle_batch_deposit_ok (
   1104   struct ExchangeGroup *eg,
   1105   const struct TALER_EXCHANGE_PostBatchDepositResponse *dr)
   1106 {
   1107   struct PayContext *pc = eg->pc;
   1108   enum GNUNET_DB_QueryStatus qs
   1109     = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   1110 
   1111   /* store result to DB */
   1112   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1113               "Storing successful payment %s (%s) at instance `%s'\n",
   1114               pc->hc->infix,
   1115               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash),
   1116               pc->hc->instance->settings.id);
   1117   for (unsigned int r = 0; r<MAX_RETRIES; r++)
   1118   {
   1119     TMH_db->preflight (TMH_db->cls);
   1120     if (GNUNET_OK !=
   1121         TMH_db->start (TMH_db->cls,
   1122                        "batch-deposit-insert-confirmation"))
   1123     {
   1124       resume_pay_with_response (
   1125         pc,
   1126         MHD_HTTP_INTERNAL_SERVER_ERROR,
   1127         TALER_MHD_MAKE_JSON_PACK (
   1128           TALER_JSON_pack_ec (
   1129             TALER_EC_GENERIC_DB_START_FAILED),
   1130           TMH_pack_exchange_reply (&dr->hr)));
   1131       return;
   1132     }
   1133     qs = batch_deposit_transaction (eg,
   1134                                     dr);
   1135     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1136     {
   1137       TMH_db->rollback (TMH_db->cls);
   1138       continue;
   1139     }
   1140     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   1141     {
   1142       GNUNET_break (0);
   1143       resume_pay_with_error (pc,
   1144                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
   1145                              "batch_deposit_transaction");
   1146       TMH_db->rollback (TMH_db->cls);
   1147       return;
   1148     }
   1149     qs = TMH_db->commit (TMH_db->cls);
   1150     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1151     {
   1152       TMH_db->rollback (TMH_db->cls);
   1153       continue;
   1154     }
   1155     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   1156     {
   1157       GNUNET_break (0);
   1158       resume_pay_with_error (pc,
   1159                              TALER_EC_GENERIC_DB_COMMIT_FAILED,
   1160                              "insert_deposit");
   1161     }
   1162     break; /* DB transaction succeeded */
   1163   }
   1164   if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   1165   {
   1166     resume_pay_with_error (pc,
   1167                            TALER_EC_GENERIC_DB_SOFT_FAILURE,
   1168                            "insert_deposit");
   1169     return;
   1170   }
   1171 
   1172   /* Transaction is done, mark affected coins as complete as well. */
   1173   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1174   {
   1175     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1176 
   1177     if (0 != strcmp (eg->exchange_url,
   1178                      dc->exchange_url))
   1179       continue;
   1180     if (dc->found_in_db)
   1181       continue;
   1182     if (! dc->in_batch)
   1183       continue;
   1184     dc->found_in_db = true;     /* well, at least NOW it'd be true ;-) */
   1185     dc->in_batch = false;
   1186     pc->pay_transaction.pending--;
   1187   }
   1188 }
   1189 
   1190 
   1191 /**
   1192  * Notify taler-merchant-kyccheck that we got a KYC
   1193  * rule violation notification and should start to
   1194  * check our KYC status.
   1195  *
   1196  * @param eg exchange group we were notified for
   1197  */
   1198 static void
   1199 notify_kyc_required (const struct ExchangeGroup *eg)
   1200 {
   1201   struct GNUNET_DB_EventHeaderP es = {
   1202     .size = htons (sizeof (es)),
   1203     .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_RULE_TRIGGERED)
   1204   };
   1205   char *hws;
   1206   char *extra;
   1207 
   1208   hws = GNUNET_STRINGS_data_to_string_alloc (
   1209     &eg->pc->check_contract.contract_terms->h_wire,
   1210     sizeof (eg->pc->check_contract.contract_terms->h_wire));
   1211   GNUNET_asprintf (&extra,
   1212                    "%s %s",
   1213                    hws,
   1214                    eg->exchange_url);
   1215   GNUNET_free (hws);
   1216   TMH_db->event_notify (TMH_db->cls,
   1217                         &es,
   1218                         extra,
   1219                         strlen (extra) + 1);
   1220   GNUNET_free (extra);
   1221 }
   1222 
   1223 
   1224 /**
   1225  * Run batch deposits for @a eg.
   1226  *
   1227  * @param[in,out] eg group to do batch deposits for
   1228  */
   1229 static void
   1230 do_batch_deposits (struct ExchangeGroup *eg);
   1231 
   1232 
   1233 /**
   1234  * Callback to handle a batch deposit permission's response.
   1235  *
   1236  * @param cls a `struct ExchangeGroup`
   1237  * @param dr HTTP response code details
   1238  */
   1239 static void
   1240 batch_deposit_cb (
   1241   void *cls,
   1242   const struct TALER_EXCHANGE_PostBatchDepositResponse *dr)
   1243 {
   1244   struct ExchangeGroup *eg = cls;
   1245   struct PayContext *pc = eg->pc;
   1246 
   1247   eg->bdh = NULL;
   1248   pc->batch_deposits.pending_at_eg--;
   1249   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1250               "Batch deposit completed with status %u\n",
   1251               dr->hr.http_status);
   1252   GNUNET_assert (GNUNET_YES == pc->suspended);
   1253   switch (dr->hr.http_status)
   1254   {
   1255   case MHD_HTTP_OK:
   1256     handle_batch_deposit_ok (eg,
   1257                              dr);
   1258     if (GNUNET_YES != pc->suspended)
   1259       return; /* handle_batch_deposit_ok already resumed with an error */
   1260     do_batch_deposits (eg);
   1261     return;
   1262   case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
   1263     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1264     {
   1265       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1266 
   1267       if (0 != strcmp (eg->exchange_url,
   1268                        dc->exchange_url))
   1269         continue;
   1270       dc->in_batch = false;
   1271     }
   1272     notify_kyc_required (eg);
   1273     eg->got_451 = true;
   1274     pc->batch_deposits.got_451 = true;
   1275     /* update pc->pay_transaction.pending */
   1276     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1277     {
   1278       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1279 
   1280       if (0 != strcmp (eg->exchange_url,
   1281                        pc->parse_pay.dc[i].exchange_url))
   1282         continue;
   1283       if (dc->found_in_db)
   1284         continue;
   1285       pc->pay_transaction.pending--;
   1286     }
   1287     if (0 == pc->batch_deposits.pending_at_eg)
   1288     {
   1289       pc->phase = PP_COMPUTE_MONEY_POTS;
   1290       pay_resume (pc);
   1291     }
   1292     return;
   1293   default:
   1294     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1295                 "Deposit operation failed with HTTP code %u/%d\n",
   1296                 dr->hr.http_status,
   1297                 (int) dr->hr.ec);
   1298     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1299     {
   1300       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1301 
   1302       if (0 != strcmp (eg->exchange_url,
   1303                        dc->exchange_url))
   1304         continue;
   1305       dc->in_batch = false;
   1306     }
   1307     /* Transaction failed */
   1308     if (5 == dr->hr.http_status / 100)
   1309     {
   1310       /* internal server error at exchange */
   1311       resume_pay_with_response (pc,
   1312                                 MHD_HTTP_BAD_GATEWAY,
   1313                                 TALER_MHD_MAKE_JSON_PACK (
   1314                                   TALER_JSON_pack_ec (
   1315                                     TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
   1316                                   TMH_pack_exchange_reply (&dr->hr)));
   1317       return;
   1318     }
   1319     if (NULL == dr->hr.reply)
   1320     {
   1321       /* We can't do anything meaningful here, the exchange did something wrong */
   1322       resume_pay_with_response (
   1323         pc,
   1324         MHD_HTTP_BAD_GATEWAY,
   1325         TALER_MHD_MAKE_JSON_PACK (
   1326           TALER_JSON_pack_ec (
   1327             TALER_EC_MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED),
   1328           TMH_pack_exchange_reply (&dr->hr)));
   1329       return;
   1330     }
   1331 
   1332     /* Forward error, adding the "exchange_url" for which the
   1333        error was being generated */
   1334     if (TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS == dr->hr.ec)
   1335     {
   1336       resume_pay_with_response (
   1337         pc,
   1338         MHD_HTTP_CONFLICT,
   1339         TALER_MHD_MAKE_JSON_PACK (
   1340           TALER_JSON_pack_ec (
   1341             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS),
   1342           TMH_pack_exchange_reply (&dr->hr),
   1343           GNUNET_JSON_pack_string ("exchange_url",
   1344                                    eg->exchange_url)));
   1345       return;
   1346     }
   1347     resume_pay_with_response (
   1348       pc,
   1349       MHD_HTTP_BAD_GATEWAY,
   1350       TALER_MHD_MAKE_JSON_PACK (
   1351         TALER_JSON_pack_ec (
   1352           TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
   1353         TMH_pack_exchange_reply (&dr->hr),
   1354         GNUNET_JSON_pack_string ("exchange_url",
   1355                                  eg->exchange_url)));
   1356     return;
   1357   } /* end switch */
   1358 }
   1359 
   1360 
   1361 static void
   1362 do_batch_deposits (struct ExchangeGroup *eg)
   1363 {
   1364   struct PayContext *pc = eg->pc;
   1365   struct TMH_HandlerContext *hc = pc->hc;
   1366   unsigned int group_size = 0;
   1367   /* Initiate /batch-deposit operation for all coins of
   1368      the current exchange (!) */
   1369 
   1370   GNUNET_assert (NULL != eg->keys);
   1371   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1372   {
   1373     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1374 
   1375     if (0 != strcmp (eg->exchange_url,
   1376                      pc->parse_pay.dc[i].exchange_url))
   1377       continue;
   1378     if (dc->found_in_db)
   1379       continue;
   1380     group_size++;
   1381     if (group_size >= TALER_MAX_COINS)
   1382       break;
   1383   }
   1384   if (0 == group_size)
   1385   {
   1386     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1387                 "Group size zero, %u batch transactions remain pending\n",
   1388                 pc->batch_deposits.pending_at_eg);
   1389     if (0 == pc->batch_deposits.pending_at_eg)
   1390     {
   1391       pc->phase = PP_COMPUTE_MONEY_POTS;
   1392       pay_resume (pc);
   1393       return;
   1394     }
   1395     return;
   1396   }
   1397   /* Dispatch the next batch of up to TALER_MAX_COINS coins.
   1398      On success, batch_deposit_cb() will re-invoke
   1399      do_batch_deposits() to send further batches until
   1400      all coins are done. */
   1401   {
   1402     struct TALER_EXCHANGE_DepositContractDetail dcd = {
   1403       .wire_deadline = pc->check_contract.contract_terms->wire_deadline,
   1404       .merchant_payto_uri = pc->check_contract.wm->payto_uri,
   1405       .extra_wire_subject_metadata
   1406         = pc->check_contract.wm->extra_wire_subject_metadata,
   1407       .wire_salt = pc->check_contract.wm->wire_salt,
   1408       .h_contract_terms = pc->check_contract.h_contract_terms,
   1409       .wallet_data_hash = pc->parse_wallet_data.h_wallet_data,
   1410       .wallet_timestamp = pc->check_contract.contract_terms->timestamp,
   1411       .merchant_pub = hc->instance->merchant_pub,
   1412       .refund_deadline = pc->check_contract.contract_terms->refund_deadline
   1413     };
   1414     /* Collect up to TALER_MAX_COINS eligible coins for this batch */
   1415     struct TALER_EXCHANGE_CoinDepositDetail cdds[group_size];
   1416     unsigned int batch_size = 0;
   1417     enum TALER_ErrorCode ec;
   1418 
   1419     /* FIXME-optimization: move signing outside of this 'loop'
   1420        and into the code that runs long before we look at a
   1421        specific exchange, otherwise we sign repeatedly! */
   1422     TALER_merchant_contract_sign (&pc->check_contract.h_contract_terms,
   1423                                   &pc->hc->instance->merchant_priv,
   1424                                   &dcd.merchant_sig);
   1425     for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1426     {
   1427       struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1428 
   1429       if (dc->found_in_db)
   1430         continue;
   1431       if (0 != strcmp (dc->exchange_url,
   1432                        eg->exchange_url))
   1433         continue;
   1434       dc->in_batch = true;
   1435       cdds[batch_size++] = dc->cdd;
   1436       if (batch_size == group_size)
   1437         break;
   1438     }
   1439     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1440                 "Initiating batch deposit with %u coins\n",
   1441                 batch_size);
   1442     /* Note: the coin signatures over the wallet_data_hash are
   1443        checked inside of this call */
   1444     eg->bdh = TALER_EXCHANGE_post_batch_deposit_create (
   1445       TMH_curl_ctx,
   1446       eg->exchange_url,
   1447       eg->keys,
   1448       &dcd,
   1449       batch_size,
   1450       cdds,
   1451       &ec);
   1452     if (NULL == eg->bdh)
   1453     {
   1454       /* Signature was invalid or some other constraint was not satisfied.  If
   1455          the exchange was unavailable, we'd get that information in the
   1456          callback. */
   1457       GNUNET_break_op (0);
   1458       resume_pay_with_response (
   1459         pc,
   1460         TALER_ErrorCode_get_http_status_safe (ec),
   1461         TALER_MHD_MAKE_JSON_PACK (
   1462           TALER_JSON_pack_ec (ec),
   1463           GNUNET_JSON_pack_string ("exchange_url",
   1464                                    eg->exchange_url)));
   1465       return;
   1466     }
   1467     pc->batch_deposits.pending_at_eg++;
   1468     if (TMH_force_audit)
   1469       TALER_EXCHANGE_post_batch_deposit_force_dc (eg->bdh);
   1470     TALER_EXCHANGE_post_batch_deposit_start (eg->bdh,
   1471                                              &batch_deposit_cb,
   1472                                              eg);
   1473   }
   1474 }
   1475 
   1476 
   1477 /**
   1478  * Force re-downloading keys for @a eg.
   1479  *
   1480  * @param[in,out] eg group to re-download keys for
   1481  */
   1482 static void
   1483 force_keys (struct ExchangeGroup *eg);
   1484 
   1485 
   1486 /**
   1487  * Function called with the result of our exchange keys lookup.
   1488  *
   1489  * @param cls the `struct ExchangeGroup`
   1490  * @param keys the keys of the exchange
   1491  * @param exchange representation of the exchange
   1492  */
   1493 static void
   1494 process_pay_with_keys (
   1495   void *cls,
   1496   struct TALER_EXCHANGE_Keys *keys,
   1497   struct TMH_Exchange *exchange)
   1498 {
   1499   struct ExchangeGroup *eg = cls;
   1500   struct PayContext *pc = eg->pc;
   1501   struct TMH_HandlerContext *hc = pc->hc;
   1502   struct TALER_Amount max_amount;
   1503   enum TMH_ExchangeStatus es;
   1504 
   1505   eg->fo = NULL;
   1506   pc->batch_deposits.pending_at_eg--;
   1507   GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id);
   1508   eg->keys = TALER_EXCHANGE_keys_incref (keys);
   1509   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1510               "Processing payment with keys from exchange %s\n",
   1511               eg->exchange_url);
   1512   GNUNET_assert (GNUNET_YES == pc->suspended);
   1513   if (NULL == keys)
   1514   {
   1515     GNUNET_break_op (0);
   1516     resume_pay_with_error (
   1517       pc,
   1518       TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
   1519       NULL);
   1520     return;
   1521   }
   1522   if (! TMH_EXCHANGES_is_below_limit (keys,
   1523                                       TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION,
   1524                                       &eg->total))
   1525   {
   1526     GNUNET_break_op (0);
   1527     resume_pay_with_error (
   1528       pc,
   1529       TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION,
   1530       eg->exchange_url);
   1531     return;
   1532   }
   1533 
   1534   max_amount = eg->total;
   1535   es = TMH_exchange_check_debit (
   1536     pc->hc->instance->settings.id,
   1537     exchange,
   1538     pc->check_contract.wm,
   1539     &max_amount);
   1540   if ( (TMH_ES_OK != es) &&
   1541        (TMH_ES_RETRY_OK != es) )
   1542   {
   1543     if (eg->tried_force_keys ||
   1544         (0 == (TMH_ES_RETRY_OK & es)) )
   1545     {
   1546       GNUNET_break_op (0);
   1547       resume_pay_with_error (
   1548         pc,
   1549         TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED,
   1550         NULL);
   1551       return;
   1552     }
   1553     force_keys (eg);
   1554     return;
   1555   }
   1556   if (-1 ==
   1557       TALER_amount_cmp (&max_amount,
   1558                         &eg->total))
   1559   {
   1560     /* max_amount < eg->total */
   1561     GNUNET_break_op (0);
   1562     resume_pay_with_error (
   1563       pc,
   1564       TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION,
   1565       eg->exchange_url);
   1566     return;
   1567   }
   1568 
   1569   if (GNUNET_OK !=
   1570       TMH_EXCHANGES_lookup_wire_fee (exchange,
   1571                                      pc->check_contract.wm->wire_method,
   1572                                      &eg->wire_fee))
   1573   {
   1574     if (eg->tried_force_keys)
   1575     {
   1576       GNUNET_break_op (0);
   1577       resume_pay_with_error (
   1578         pc,
   1579         TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED,
   1580         pc->check_contract.wm->wire_method);
   1581       return;
   1582     }
   1583     force_keys (eg);
   1584     return;
   1585   }
   1586   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1587               "Got wire data for %s\n",
   1588               eg->exchange_url);
   1589 
   1590   /* Check all coins satisfy constraints like deposit deadlines
   1591      and age restrictions */
   1592   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   1593   {
   1594     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   1595     const struct TALER_EXCHANGE_DenomPublicKey *denom_details;
   1596     bool is_age_restricted_denom = false;
   1597 
   1598     if (0 != strcmp (eg->exchange_url,
   1599                      pc->parse_pay.dc[i].exchange_url))
   1600       continue;
   1601     if (dc->found_in_db)
   1602       continue;
   1603 
   1604     denom_details
   1605       = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
   1606                                                      &dc->cdd.h_denom_pub);
   1607     if (NULL == denom_details)
   1608     {
   1609       if (eg->tried_force_keys)
   1610       {
   1611         GNUNET_break_op (0);
   1612         resume_pay_with_response (
   1613           pc,
   1614           MHD_HTTP_BAD_REQUEST,
   1615           TALER_MHD_MAKE_JSON_PACK (
   1616             TALER_JSON_pack_ec (
   1617               TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND),
   1618             GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1619                                         &dc->cdd.h_denom_pub),
   1620             GNUNET_JSON_pack_allow_null (
   1621               GNUNET_JSON_pack_object_steal (
   1622                 "exchange_keys",
   1623                 TALER_EXCHANGE_keys_to_json (keys)))));
   1624         return;
   1625       }
   1626       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1627                   "Missing denomination %s from exchange %s, updating keys\n",
   1628                   GNUNET_h2s (&dc->cdd.h_denom_pub.hash),
   1629                   eg->exchange_url);
   1630       force_keys (eg);
   1631       return;
   1632     }
   1633     dc->deposit_fee = denom_details->fees.deposit;
   1634     dc->refund_fee = denom_details->fees.refund;
   1635 
   1636     if (GNUNET_TIME_absolute_is_past (
   1637           denom_details->expire_deposit.abs_time))
   1638     {
   1639       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1640                   "Denomination key offered by client has expired for deposits\n");
   1641       resume_pay_with_response (
   1642         pc,
   1643         MHD_HTTP_GONE,
   1644         TALER_MHD_MAKE_JSON_PACK (
   1645           TALER_JSON_pack_ec (
   1646             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED),
   1647           GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1648                                       &denom_details->h_key)));
   1649       return;
   1650     }
   1651 
   1652     /* Now that we have the details about the denomination, we can verify age
   1653      * restriction requirements, if applicable. Note that denominations with an
   1654      * age_mask equal to zero always pass the age verification.  */
   1655     is_age_restricted_denom = (0 != denom_details->key.age_mask.bits);
   1656 
   1657     if (is_age_restricted_denom &&
   1658         (0 < pc->check_contract.contract_terms->minimum_age))
   1659     {
   1660       /* Minimum age given and restricted coin provided: We need to verify the
   1661        * minimum age */
   1662       unsigned int code = 0;
   1663 
   1664       if (dc->no_age_commitment)
   1665       {
   1666         GNUNET_break_op (0);
   1667         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING;
   1668         goto AGE_FAIL;
   1669       }
   1670       dc->age_commitment.mask = denom_details->key.age_mask;
   1671       if (((int) (dc->age_commitment.num + 1)) !=
   1672           __builtin_popcount (dc->age_commitment.mask.bits))
   1673       {
   1674         GNUNET_break_op (0);
   1675         code =
   1676           TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH;
   1677         goto AGE_FAIL;
   1678       }
   1679       if (GNUNET_OK !=
   1680           TALER_age_commitment_verify (
   1681             &dc->age_commitment,
   1682             pc->check_contract.contract_terms->minimum_age,
   1683             &dc->minimum_age_sig))
   1684         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED;
   1685 AGE_FAIL:
   1686       if (0 < code)
   1687       {
   1688         GNUNET_break_op (0);
   1689         TALER_age_commitment_free (&dc->age_commitment);
   1690         resume_pay_with_response (
   1691           pc,
   1692           MHD_HTTP_BAD_REQUEST,
   1693           TALER_MHD_MAKE_JSON_PACK (
   1694             TALER_JSON_pack_ec (code),
   1695             GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1696                                         &denom_details->h_key)));
   1697         return;
   1698       }
   1699 
   1700       /* Age restriction successfully verified!
   1701        * Calculate the hash of the age commitment. */
   1702       TALER_age_commitment_hash (&dc->age_commitment,
   1703                                  &dc->cdd.h_age_commitment);
   1704       TALER_age_commitment_free (&dc->age_commitment);
   1705     }
   1706     else if (is_age_restricted_denom &&
   1707              dc->no_h_age_commitment)
   1708     {
   1709       /* The contract did not ask for a minimum_age but the client paid
   1710        * with a coin that has age restriction enabled.  We lack the hash
   1711        * of the age commitment in this case in order to verify the coin
   1712        * and to deposit it with the exchange. */
   1713       GNUNET_break_op (0);
   1714       resume_pay_with_response (
   1715         pc,
   1716         MHD_HTTP_BAD_REQUEST,
   1717         TALER_MHD_MAKE_JSON_PACK (
   1718           TALER_JSON_pack_ec (
   1719             TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING),
   1720           GNUNET_JSON_pack_data_auto ("h_denom_pub",
   1721                                       &denom_details->h_key)));
   1722       return;
   1723     }
   1724   }
   1725 
   1726   do_batch_deposits (eg);
   1727 }
   1728 
   1729 
   1730 static void
   1731 force_keys (struct ExchangeGroup *eg)
   1732 {
   1733   struct PayContext *pc = eg->pc;
   1734 
   1735   eg->tried_force_keys = true;
   1736   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1737               "Forcing /keys download (once)\n");
   1738   eg->fo = TMH_EXCHANGES_keys4exchange (
   1739     eg->exchange_url,
   1740     true,
   1741     &process_pay_with_keys,
   1742     eg);
   1743   if (NULL == eg->fo)
   1744   {
   1745     GNUNET_break_op (0);
   1746     resume_pay_with_error (pc,
   1747                            TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED,
   1748                            eg->exchange_url);
   1749     return;
   1750   }
   1751   pc->batch_deposits.pending_at_eg++;
   1752 }
   1753 
   1754 
   1755 /**
   1756  * Handle a timeout for the processing of the pay request.
   1757  *
   1758  * @param cls our `struct PayContext`
   1759  */
   1760 static void
   1761 handle_pay_timeout (void *cls)
   1762 {
   1763   struct PayContext *pc = cls;
   1764 
   1765   pc->batch_deposits.timeout_task = NULL;
   1766   GNUNET_assert (GNUNET_YES == pc->suspended);
   1767   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1768               "Resuming pay with error after timeout\n");
   1769   resume_pay_with_error (pc,
   1770                          TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
   1771                          NULL);
   1772 }
   1773 
   1774 
   1775 /**
   1776  * Compute the timeout for a /pay request based on the number of coins
   1777  * involved.
   1778  *
   1779  * @param num_coins number of coins
   1780  * @returns timeout for the /pay request
   1781  */
   1782 static struct GNUNET_TIME_Relative
   1783 get_pay_timeout (unsigned int num_coins)
   1784 {
   1785   struct GNUNET_TIME_Relative t;
   1786 
   1787   /* FIXME-Performance-Optimization: Do some benchmarking to come up with a
   1788    * better timeout.  We've increased this value so the wallet integration
   1789    * test passes again on my (Florian) machine.
   1790    */
   1791   t = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
   1792                                      15 * (1 + (num_coins / 5)));
   1793 
   1794   return t;
   1795 }
   1796 
   1797 
   1798 /**
   1799  * Start batch deposits for all exchanges involved
   1800  * in this payment.
   1801  *
   1802  * @param[in,out] pc payment context we are processing
   1803  */
   1804 static void
   1805 phase_batch_deposits (struct PayContext *pc)
   1806 {
   1807   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   1808   {
   1809     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   1810     bool have_coins = false;
   1811 
   1812     for (size_t j = 0; j<pc->parse_pay.coins_cnt; j++)
   1813     {
   1814       struct DepositConfirmation *dc = &pc->parse_pay.dc[j];
   1815 
   1816       if (0 != strcmp (eg->exchange_url,
   1817                        dc->exchange_url))
   1818         continue;
   1819       if (dc->found_in_db)
   1820         continue;
   1821       have_coins = true;
   1822       break;
   1823     }
   1824     if (! have_coins)
   1825       continue; /* no coins left to deposit at this exchange */
   1826     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1827                 "Getting /keys for %s\n",
   1828                 eg->exchange_url);
   1829     eg->fo = TMH_EXCHANGES_keys4exchange (
   1830       eg->exchange_url,
   1831       false,
   1832       &process_pay_with_keys,
   1833       eg);
   1834     if (NULL == eg->fo)
   1835     {
   1836       GNUNET_break_op (0);
   1837       pay_end (pc,
   1838                TALER_MHD_reply_with_error (
   1839                  pc->connection,
   1840                  MHD_HTTP_BAD_REQUEST,
   1841                  TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED,
   1842                  eg->exchange_url));
   1843       return;
   1844     }
   1845     pc->batch_deposits.pending_at_eg++;
   1846   }
   1847   if (0 == pc->batch_deposits.pending_at_eg)
   1848   {
   1849     pc->phase = PP_COMPUTE_MONEY_POTS;
   1850     pay_resume (pc);
   1851     return;
   1852   }
   1853   /* Suspend while we interact with the exchange */
   1854   MHD_suspend_connection (pc->connection);
   1855   pc->suspended = GNUNET_YES;
   1856   GNUNET_assert (NULL == pc->batch_deposits.timeout_task);
   1857   pc->batch_deposits.timeout_task
   1858     = GNUNET_SCHEDULER_add_delayed (get_pay_timeout (pc->parse_pay.coins_cnt),
   1859                                     &handle_pay_timeout,
   1860                                     pc);
   1861 }
   1862 
   1863 
   1864 /**
   1865  * Build JSON array of blindly signed token envelopes,
   1866  * to be used in the response to the wallet.
   1867  *
   1868  * @param[in,out] pc payment context to use
   1869  */
   1870 static json_t *
   1871 build_token_sigs (struct PayContext *pc)
   1872 {
   1873   json_t *token_sigs;
   1874 
   1875   if (0 == pc->output_tokens_len)
   1876     return NULL;
   1877   token_sigs = json_array ();
   1878   GNUNET_assert (NULL != token_sigs);
   1879   for (unsigned int i = 0; i < pc->output_tokens_len; i++)
   1880   {
   1881     GNUNET_assert (0 ==
   1882                    json_array_append_new (
   1883                      token_sigs,
   1884                      GNUNET_JSON_PACK (
   1885                        GNUNET_JSON_pack_blinded_sig (
   1886                          "blind_sig",
   1887                          pc->output_tokens[i].sig.signature)
   1888                        )));
   1889   }
   1890   return token_sigs;
   1891 }
   1892 
   1893 
   1894 /**
   1895  * Generate response (payment successful)
   1896  *
   1897  * @param[in,out] pc payment context where the payment was successful
   1898  */
   1899 static void
   1900 phase_success_response (struct PayContext *pc)
   1901 {
   1902   struct TALER_MerchantSignatureP sig;
   1903   char *pos_confirmation;
   1904 
   1905   /* Sign on our end (as the payment did go through, even if it may
   1906      have been refunded already) */
   1907   TALER_merchant_pay_sign (&pc->check_contract.h_contract_terms,
   1908                            &pc->hc->instance->merchant_priv,
   1909                            &sig);
   1910   /* Build the response */
   1911   pos_confirmation = (NULL == pc->check_contract.pos_key)
   1912     ? NULL
   1913     : TALER_build_pos_confirmation (pc->check_contract.pos_key,
   1914                                     pc->check_contract.pos_alg,
   1915                                     &pc->validate_tokens.brutto,
   1916                                     pc->check_contract.contract_terms->timestamp
   1917                                     );
   1918   pay_end (pc,
   1919            TALER_MHD_REPLY_JSON_PACK (
   1920              pc->connection,
   1921              MHD_HTTP_OK,
   1922              GNUNET_JSON_pack_allow_null (
   1923                GNUNET_JSON_pack_string ("pos_confirmation",
   1924                                         pos_confirmation)),
   1925              GNUNET_JSON_pack_allow_null (
   1926                GNUNET_JSON_pack_array_steal ("token_sigs",
   1927                                              build_token_sigs (pc))),
   1928              GNUNET_JSON_pack_data_auto ("sig",
   1929                                          &sig)));
   1930   GNUNET_free (pos_confirmation);
   1931 }
   1932 
   1933 
   1934 /**
   1935  * Use database to notify other clients about the
   1936  * payment being completed.
   1937  *
   1938  * @param[in,out] pc context to trigger notification for
   1939  */
   1940 static void
   1941 phase_payment_notification (struct PayContext *pc)
   1942 {
   1943   {
   1944     struct TMH_OrderPayEventP pay_eh = {
   1945       .header.size = htons (sizeof (pay_eh)),
   1946       .header.type = htons (TALER_DBEVENT_MERCHANT_ORDER_PAID),
   1947       .merchant_pub = pc->hc->instance->merchant_pub
   1948     };
   1949 
   1950     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1951                 "Notifying clients about payment of order %s\n",
   1952                 pc->order_id);
   1953     GNUNET_CRYPTO_hash (pc->order_id,
   1954                         strlen (pc->order_id),
   1955                         &pay_eh.h_order_id);
   1956     TMH_db->event_notify (TMH_db->cls,
   1957                           &pay_eh.header,
   1958                           NULL,
   1959                           0);
   1960   }
   1961   {
   1962     struct TMH_OrderPayEventP pay_eh = {
   1963       .header.size = htons (sizeof (pay_eh)),
   1964       .header.type = htons (TALER_DBEVENT_MERCHANT_ORDER_STATUS_CHANGED),
   1965       .merchant_pub = pc->hc->instance->merchant_pub
   1966     };
   1967 
   1968     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1969                 "Notifying clients about status change of order %s\n",
   1970                 pc->order_id);
   1971     GNUNET_CRYPTO_hash (pc->order_id,
   1972                         strlen (pc->order_id),
   1973                         &pay_eh.h_order_id);
   1974     TMH_db->event_notify (TMH_db->cls,
   1975                           &pay_eh.header,
   1976                           NULL,
   1977                           0);
   1978   }
   1979   if ( (NULL != pc->parse_pay.session_id) &&
   1980        (NULL != pc->check_contract.contract_terms->fulfillment_url) )
   1981   {
   1982     struct TMH_SessionEventP session_eh = {
   1983       .header.size = htons (sizeof (session_eh)),
   1984       .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED),
   1985       .merchant_pub = pc->hc->instance->merchant_pub
   1986     };
   1987 
   1988     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1989                 "Notifying clients about session change to %s for %s\n",
   1990                 pc->parse_pay.session_id,
   1991                 pc->check_contract.contract_terms->fulfillment_url);
   1992     GNUNET_CRYPTO_hash (pc->parse_pay.session_id,
   1993                         strlen (pc->parse_pay.session_id),
   1994                         &session_eh.h_session_id);
   1995     GNUNET_CRYPTO_hash (pc->check_contract.contract_terms->fulfillment_url,
   1996                         strlen (pc->check_contract.contract_terms->
   1997                                 fulfillment_url),
   1998                         &session_eh.h_fulfillment_url);
   1999     TMH_db->event_notify (TMH_db->cls,
   2000                           &session_eh.header,
   2001                           NULL,
   2002                           0);
   2003   }
   2004   pc->phase = PP_SUCCESS_RESPONSE;
   2005 }
   2006 
   2007 
   2008 /**
   2009  * Phase to write all outputs to our database so we do
   2010  * not re-request them in case the client re-plays the
   2011  * request.
   2012  *
   2013  * @param[in,out] pc payment context
   2014  */
   2015 static void
   2016 phase_final_output_token_processing (struct PayContext *pc)
   2017 {
   2018   if (0 == pc->output_tokens_len)
   2019   {
   2020     pc->phase++;
   2021     return;
   2022   }
   2023   for (unsigned int retry = 0; retry < MAX_RETRIES; retry++)
   2024   {
   2025     enum GNUNET_DB_QueryStatus qs;
   2026 
   2027     TMH_db->preflight (TMH_db->cls);
   2028     if (GNUNET_OK !=
   2029         TMH_db->start (TMH_db->cls,
   2030                        "insert_order_blinded_sigs"))
   2031     {
   2032       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2033                   "start insert_order_blinded_sigs_failed");
   2034       pc->phase++;
   2035       return;
   2036     }
   2037 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   2038     if (pc->parse_wallet_data.num_bkps > 0)
   2039     {
   2040       qs = TMH_db->update_donau_instance_receipts_amount (
   2041         TMH_db->cls,
   2042         &pc->parse_wallet_data.donau_instance_serial,
   2043         &pc->parse_wallet_data.charity_receipts_to_date);
   2044       switch (qs)
   2045       {
   2046       case GNUNET_DB_STATUS_HARD_ERROR:
   2047         TMH_db->rollback (TMH_db->cls);
   2048         GNUNET_break (0);
   2049         return;
   2050       case GNUNET_DB_STATUS_SOFT_ERROR:
   2051         TMH_db->rollback (TMH_db->cls);
   2052         continue;
   2053       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2054         /* weird for an update */
   2055         GNUNET_break (0);
   2056         break;
   2057       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2058         break;
   2059       }
   2060     }
   2061 #endif
   2062     for (unsigned int i = 0;
   2063          i < pc->output_tokens_len;
   2064          i++)
   2065     {
   2066       qs = TMH_db->insert_order_blinded_sigs (
   2067         TMH_db->cls,
   2068         pc->order_id,
   2069         i,
   2070         &pc->output_tokens[i].h_issue.hash,
   2071         pc->output_tokens[i].sig.signature);
   2072 
   2073       switch (qs)
   2074       {
   2075       case GNUNET_DB_STATUS_HARD_ERROR:
   2076         TMH_db->rollback (TMH_db->cls);
   2077         pc->phase++;
   2078         return;
   2079       case GNUNET_DB_STATUS_SOFT_ERROR:
   2080         TMH_db->rollback (TMH_db->cls);
   2081         goto OUTER;
   2082       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2083         /* weird for an update */
   2084         GNUNET_break (0);
   2085         break;
   2086       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2087         break;
   2088       }
   2089     } /* for i */
   2090     qs = TMH_db->commit (TMH_db->cls);
   2091     switch (qs)
   2092     {
   2093     case GNUNET_DB_STATUS_HARD_ERROR:
   2094       TMH_db->rollback (TMH_db->cls);
   2095       pc->phase++;
   2096       return;
   2097     case GNUNET_DB_STATUS_SOFT_ERROR:
   2098       TMH_db->rollback (TMH_db->cls);
   2099       continue;
   2100     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2101       pc->phase++;
   2102       return; /* success */
   2103     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2104       pc->phase++;
   2105       return; /* success */
   2106     }
   2107     GNUNET_break (0);
   2108     pc->phase++;
   2109     return; /* strange */
   2110 OUTER:
   2111   } /* for retry */
   2112   TMH_db->rollback (TMH_db->cls);
   2113   pc->phase++;
   2114   /* We continue anyway, as there is not much we can
   2115      do here: the Donau *did* issue us the receipts;
   2116      also, we'll eventually ask the Donau for the
   2117      balance and get the correct one. Plus, we were
   2118      paid by the client, so it's technically all still
   2119      OK. If the request fails anyway, the wallet will
   2120      most likely replay the request and then hopefully
   2121      we will succeed the next time */
   2122 }
   2123 
   2124 
   2125 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   2126 
   2127 /**
   2128  * Add donation receipt outputs to the output_tokens.
   2129  *
   2130  * Note that under the current (odd, bad) libdonau
   2131  * API *we* are responsible for freeing blinded_sigs,
   2132  * so we truly own that array!
   2133  *
   2134  * @param[in,out] pc payment context
   2135  * @param num_blinded_sigs number of signatures received
   2136  * @param blinded_sigs blinded signatures from Donau
   2137  * @return #GNUNET_OK on success,
   2138  *         #GNUNET_SYSERR on failure (state machine was
   2139  *          in that case already advanced)
   2140  */
   2141 static enum GNUNET_GenericReturnValue
   2142 add_donation_receipt_outputs (
   2143   struct PayContext *pc,
   2144   size_t num_blinded_sigs,
   2145   struct DONAU_BlindedDonationUnitSignature *blinded_sigs)
   2146 {
   2147   int donau_output_index = pc->validate_tokens.donau_output_index;
   2148 
   2149   GNUNET_assert (pc->parse_wallet_data.num_bkps ==
   2150                  num_blinded_sigs);
   2151 
   2152   GNUNET_assert (donau_output_index >= 0);
   2153 
   2154   for (unsigned int i = 0; i<pc->output_tokens_len; i++)
   2155   {
   2156     struct SignedOutputToken *sot
   2157       = &pc->output_tokens[i];
   2158 
   2159     /* Only look at actual donau tokens. */
   2160     if (sot->output_index != donau_output_index)
   2161       continue;
   2162 
   2163     sot->sig.signature = GNUNET_CRYPTO_blind_sig_incref (blinded_sigs[i].
   2164                                                          blinded_sig);
   2165     sot->h_issue.hash = pc->parse_wallet_data.bkps[i].h_donation_unit_pub.hash;
   2166   }
   2167   return GNUNET_OK;
   2168 }
   2169 
   2170 
   2171 /**
   2172  * Callback to handle the result of a batch issue request.
   2173  *
   2174  * @param cls our `struct PayContext`
   2175  * @param resp the response from Donau
   2176  */
   2177 static void
   2178 merchant_donau_issue_receipt_cb (
   2179   void *cls,
   2180   const struct DONAU_BatchIssueResponse *resp)
   2181 {
   2182   struct PayContext *pc = cls;
   2183   /* Donau replies asynchronously, so we expect the PayContext
   2184    * to be suspended. */
   2185   GNUNET_assert (GNUNET_YES == pc->suspended);
   2186   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2187               "Donau responded with status=%u, ec=%u",
   2188               resp->hr.http_status,
   2189               resp->hr.ec);
   2190   switch (resp->hr.http_status)
   2191   {
   2192   case 0:
   2193     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2194                 "Donau batch issue request from merchant-httpd failed (http_status==0)");
   2195     resume_pay_with_error (pc,
   2196                            TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE,
   2197                            resp->hr.hint);
   2198     return;
   2199   case MHD_HTTP_OK:
   2200   case MHD_HTTP_CREATED:
   2201     if (TALER_EC_NONE != resp->hr.ec)
   2202     {
   2203       /* Most probably, it is just some small flaw from
   2204        * donau so no point in failing, yet we have to display it */
   2205       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2206                   "Donau signalled error %u despite HTTP %u",
   2207                   resp->hr.ec,
   2208                   resp->hr.http_status);
   2209     }
   2210     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2211                 "Donau accepted donation receipts with total_issued=%s",
   2212                 TALER_amount2s (&resp->details.ok.issued_amount));
   2213     if (GNUNET_OK !=
   2214         add_donation_receipt_outputs (pc,
   2215                                       resp->details.ok.num_blinded_sigs,
   2216                                       resp->details.ok.blinded_sigs))
   2217       return; /* state machine was already advanced */
   2218     pc->phase = PP_FINAL_OUTPUT_TOKEN_PROCESSING;
   2219     pay_resume (pc);
   2220     return;
   2221 
   2222   case MHD_HTTP_BAD_REQUEST:
   2223   case MHD_HTTP_FORBIDDEN:
   2224   case MHD_HTTP_NOT_FOUND:
   2225   case MHD_HTTP_INTERNAL_SERVER_ERROR:
   2226   default: /* make sure that everything except 200/201 will end up here*/
   2227     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2228                 "Donau replied with HTTP %u (ec=%u)",
   2229                 resp->hr.http_status,
   2230                 resp->hr.ec);
   2231     resume_pay_with_error (pc,
   2232                            TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE,
   2233                            resp->hr.hint);
   2234     return;
   2235   }
   2236 }
   2237 
   2238 
   2239 /**
   2240  * Parse a bkp encoded in JSON.
   2241  *
   2242  * @param[out] bkp where to return the result
   2243  * @param bkp_key_obj json to parse
   2244  * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if @a bkp_key_obj
   2245  * is malformed.
   2246  */
   2247 static enum GNUNET_GenericReturnValue
   2248 merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp,
   2249                          const json_t *bkp_key_obj)
   2250 {
   2251   struct GNUNET_JSON_Specification spec[] = {
   2252     GNUNET_JSON_spec_fixed_auto ("h_donation_unit_pub",
   2253                                  &bkp->h_donation_unit_pub),
   2254     DONAU_JSON_spec_blinded_donation_identifier ("blinded_udi",
   2255                                                  &bkp->blinded_udi),
   2256     GNUNET_JSON_spec_end ()
   2257   };
   2258 
   2259   if (GNUNET_OK !=
   2260       GNUNET_JSON_parse (bkp_key_obj,
   2261                          spec,
   2262                          NULL,
   2263                          NULL))
   2264   {
   2265     GNUNET_break_op (0);
   2266     return GNUNET_SYSERR;
   2267   }
   2268   return GNUNET_OK;
   2269 }
   2270 
   2271 
   2272 /**
   2273  * Generate a donation signature for the bkp and charity.
   2274  *
   2275  * @param[in,out] pc payment context containing the charity and bkps
   2276  */
   2277 static void
   2278 phase_request_donation_receipt (struct PayContext *pc)
   2279 {
   2280   if ( (NULL == pc->parse_wallet_data.donau.donau_url) ||
   2281        (0 == pc->parse_wallet_data.num_bkps) )
   2282   {
   2283     pc->phase++;
   2284     return;
   2285   }
   2286   pc->donau_receipt.birh =
   2287     DONAU_charity_issue_receipt (
   2288       TMH_curl_ctx,
   2289       pc->parse_wallet_data.donau.donau_url,
   2290       &pc->parse_wallet_data.charity_priv,
   2291       pc->parse_wallet_data.charity_id,
   2292       pc->parse_wallet_data.donau.donation_year,
   2293       pc->parse_wallet_data.num_bkps,
   2294       pc->parse_wallet_data.bkps,
   2295       &merchant_donau_issue_receipt_cb,
   2296       pc);
   2297   if (NULL == pc->donau_receipt.birh)
   2298   {
   2299     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2300                 "Failed to create Donau receipt request");
   2301     pay_end (pc,
   2302              TALER_MHD_reply_with_error (pc->connection,
   2303                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2304                                          TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
   2305                                          "Donau request creation error"));
   2306     return;
   2307   }
   2308   MHD_suspend_connection (pc->connection);
   2309   pc->suspended = GNUNET_YES;
   2310 }
   2311 
   2312 
   2313 #endif
   2314 
   2315 
   2316 /**
   2317  * Increment the money pot @a pot_id in @a pc by @a increment.
   2318  *
   2319  * @param[in,out] pc context to update
   2320  * @param pot_id money pot to increment
   2321  * @param increment amount to add
   2322  */
   2323 static void
   2324 increment_pot (struct PayContext *pc,
   2325                uint64_t pot_id,
   2326                const struct TALER_Amount *increment)
   2327 {
   2328   for (unsigned int i = 0; i<pc->compute_money_pots.num_pots; i++)
   2329   {
   2330     if (pot_id == pc->compute_money_pots.pots[i])
   2331     {
   2332       struct TALER_Amount *p;
   2333 
   2334       p = &pc->compute_money_pots.increments[i];
   2335       GNUNET_assert (0 <=
   2336                      TALER_amount_add (p,
   2337                                        p,
   2338                                        increment));
   2339       return;
   2340     }
   2341   }
   2342   GNUNET_array_append (pc->compute_money_pots.pots,
   2343                        pc->compute_money_pots.num_pots,
   2344                        pot_id);
   2345   pc->compute_money_pots.num_pots--; /* do not increment twice... */
   2346   GNUNET_array_append (pc->compute_money_pots.increments,
   2347                        pc->compute_money_pots.num_pots,
   2348                        *increment);
   2349 }
   2350 
   2351 
   2352 /**
   2353  * Compute the total changes to money pots in preparation
   2354  * for the #PP_PAY_TRANSACTION phase.
   2355  *
   2356  * @param[in,out] pc payment context to transact
   2357  */
   2358 static void
   2359 phase_compute_money_pots (struct PayContext *pc)
   2360 {
   2361   const struct TALER_MERCHANT_Contract *contract
   2362     = pc->check_contract.contract_terms;
   2363   struct TALER_Amount assigned;
   2364 
   2365   if (0 == pc->parse_pay.coins_cnt)
   2366   {
   2367     /* Did not pay with any coins, so no currency/amount involved,
   2368        hence no money pot update possible. */
   2369     pc->phase++;
   2370     return;
   2371   }
   2372 
   2373   if (pc->compute_money_pots.pots_computed)
   2374   {
   2375     pc->phase++;
   2376     return;
   2377   }
   2378   /* reset, in case this phase is run a 2nd time */
   2379   GNUNET_free (pc->compute_money_pots.pots);
   2380   GNUNET_free (pc->compute_money_pots.increments);
   2381   pc->compute_money_pots.num_pots = 0;
   2382 
   2383   TALER_amount_set_zero (pc->parse_pay.dc[0].cdd.amount.currency,
   2384                          &assigned);
   2385   GNUNET_assert (NULL != contract);
   2386   for (size_t i = 0; i<contract->products_len; i++)
   2387   {
   2388     const struct TALER_MERCHANT_ProductSold *product
   2389       = &contract->products[i];
   2390     const struct TALER_Amount *price = NULL;
   2391 
   2392     /* find price in the right currency */
   2393     for (unsigned int j = 0; j<product->prices_length; j++)
   2394     {
   2395       if (GNUNET_OK ==
   2396           TALER_amount_cmp_currency (&assigned,
   2397                                      &product->prices[j]))
   2398       {
   2399         price = &product->prices[j];
   2400         break;
   2401       }
   2402     }
   2403     if (NULL == price)
   2404     {
   2405       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2406                   "Product `%s' has no price given in `%s'.\n",
   2407                   product->product_id,
   2408                   assigned.currency);
   2409       continue;
   2410     }
   2411     if (0 != product->product_money_pot)
   2412     {
   2413       GNUNET_assert (0 <=
   2414                      TALER_amount_add (&assigned,
   2415                                        &assigned,
   2416                                        price));
   2417       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2418                   "Contributing to product money pot %llu increment of %s\n",
   2419                   (unsigned long long) product->product_money_pot,
   2420                   TALER_amount2s (price));
   2421       increment_pot (pc,
   2422                      product->product_money_pot,
   2423                      price);
   2424     }
   2425   }
   2426 
   2427   {
   2428     /* Compute what is left from the order total and account for that.
   2429        Also sanity-check and handle the case where the overall order
   2430        is below that of the sum of the products. */
   2431     struct TALER_Amount left;
   2432 
   2433     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2434                 "Order brutto is %s\n",
   2435                 TALER_amount2s (&pc->validate_tokens.brutto));
   2436     if (0 >
   2437         TALER_amount_subtract (&left,
   2438                                &pc->validate_tokens.brutto,
   2439                                &assigned))
   2440     {
   2441       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2442                   "Total order brutto amount below sum from products, skipping per-product money pots\n");
   2443       GNUNET_free (pc->compute_money_pots.pots);
   2444       GNUNET_free (pc->compute_money_pots.increments);
   2445       pc->compute_money_pots.num_pots = 0;
   2446       left = pc->validate_tokens.brutto;
   2447     }
   2448 
   2449     if ( (! TALER_amount_is_zero (&left)) &&
   2450          (0 != contract->default_money_pot) )
   2451     {
   2452       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2453                   "Computing money pot %llu increment as %s\n",
   2454                   (unsigned long long) contract->default_money_pot,
   2455                   TALER_amount2s (&left));
   2456       increment_pot (pc,
   2457                      contract->default_money_pot,
   2458                      &left);
   2459     }
   2460   }
   2461   pc->compute_money_pots.pots_computed = true;
   2462   pc->phase++;
   2463 }
   2464 
   2465 
   2466 /**
   2467  * Function called with information about a coin that was deposited.
   2468  *
   2469  * @param cls closure
   2470  * @param exchange_url exchange where @a coin_pub was deposited
   2471  * @param coin_pub public key of the coin
   2472  * @param amount_with_fee amount the exchange will deposit for this coin
   2473  * @param deposit_fee fee the exchange will charge for this coin
   2474  * @param refund_fee fee the exchange will charge for refunding this coin
   2475  */
   2476 static void
   2477 check_coin_paid (void *cls,
   2478                  const char *exchange_url,
   2479                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2480                  const struct TALER_Amount *amount_with_fee,
   2481                  const struct TALER_Amount *deposit_fee,
   2482                  const struct TALER_Amount *refund_fee)
   2483 {
   2484   struct PayContext *pc = cls;
   2485 
   2486   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2487   {
   2488     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2489 
   2490     if (dc->found_in_db)
   2491       continue; /* processed earlier, skip "expensive" memcmp() */
   2492     /* Get matching coin from results*/
   2493     if ( (0 != GNUNET_memcmp (coin_pub,
   2494                               &dc->cdd.coin_pub)) ||
   2495          (0 !=
   2496           strcmp (exchange_url,
   2497                   dc->exchange_url)) ||
   2498          (GNUNET_OK !=
   2499           TALER_amount_cmp_currency (amount_with_fee,
   2500                                      &dc->cdd.amount)) ||
   2501          (0 != TALER_amount_cmp (amount_with_fee,
   2502                                  &dc->cdd.amount)) )
   2503       continue; /* does not match, skip */
   2504     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2505                 "Deposit of coin `%s' already in our DB.\n",
   2506                 TALER_B2S (coin_pub));
   2507     if ( (GNUNET_OK !=
   2508           TALER_amount_cmp_currency (&pc->pay_transaction.total_paid,
   2509                                      amount_with_fee)) ||
   2510          (GNUNET_OK !=
   2511           TALER_amount_cmp_currency (&pc->pay_transaction.total_fees_paid,
   2512                                      deposit_fee)) )
   2513     {
   2514       GNUNET_break_op (0);
   2515       pc->pay_transaction.deposit_currency_mismatch = true;
   2516       break;
   2517     }
   2518     GNUNET_assert (0 <=
   2519                    TALER_amount_add (&pc->pay_transaction.total_paid,
   2520                                      &pc->pay_transaction.total_paid,
   2521                                      amount_with_fee));
   2522     GNUNET_assert (0 <=
   2523                    TALER_amount_add (&pc->pay_transaction.total_fees_paid,
   2524                                      &pc->pay_transaction.total_fees_paid,
   2525                                      deposit_fee));
   2526     dc->deposit_fee = *deposit_fee;
   2527     dc->refund_fee = *refund_fee;
   2528     dc->cdd.amount = *amount_with_fee;
   2529     dc->found_in_db = true;
   2530     pc->pay_transaction.pending--;
   2531   }
   2532 }
   2533 
   2534 
   2535 /**
   2536  * Function called with information about a refund.  Check if this coin was
   2537  * claimed by the wallet for the transaction, and if so add the refunded
   2538  * amount to the pc's "total_refunded" amount.
   2539  *
   2540  * @param cls closure with a `struct PayContext`
   2541  * @param coin_pub public coin from which the refund comes from
   2542  * @param refund_amount refund amount which is being taken from @a coin_pub
   2543  */
   2544 static void
   2545 check_coin_refunded (void *cls,
   2546                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
   2547                      const struct TALER_Amount *refund_amount)
   2548 {
   2549   struct PayContext *pc = cls;
   2550 
   2551   /* We look at refunds here that apply to the coins
   2552      that the customer is currently trying to pay us with.
   2553 
   2554      Such refunds are not "normal" refunds, but abort-pay refunds, which are
   2555      given in the case that the wallet aborts the payment.
   2556      In the case the wallet then decides to complete the payment *after* doing
   2557      an abort-pay refund (an unusual but possible case), we need
   2558      to make sure that existing refunds are accounted for. */
   2559 
   2560   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2561   {
   2562     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2563 
   2564     /* Get matching coins from results.  */
   2565     if (0 != GNUNET_memcmp (coin_pub,
   2566                             &dc->cdd.coin_pub))
   2567       continue;
   2568     if (GNUNET_OK !=
   2569         TALER_amount_cmp_currency (&pc->pay_transaction.total_refunded,
   2570                                    refund_amount))
   2571     {
   2572       GNUNET_break (0);
   2573       pc->pay_transaction.refund_currency_mismatch = true;
   2574       break;
   2575     }
   2576     GNUNET_assert (0 <=
   2577                    TALER_amount_add (&pc->pay_transaction.total_refunded,
   2578                                      &pc->pay_transaction.total_refunded,
   2579                                      refund_amount));
   2580     break;
   2581   }
   2582 }
   2583 
   2584 
   2585 /**
   2586  * Check whether the amount paid is sufficient to cover the price.
   2587  *
   2588  * @param pc payment context to check
   2589  * @return true if the payment is sufficient, false if it is
   2590  *         insufficient
   2591  */
   2592 static bool
   2593 check_payment_sufficient (struct PayContext *pc)
   2594 {
   2595   struct TALER_Amount acc_fee;
   2596   struct TALER_Amount acc_amount;
   2597   struct TALER_Amount final_amount;
   2598   struct TALER_Amount total_wire_fee;
   2599   struct TALER_Amount total_needed;
   2600 
   2601   if (0 == pc->parse_pay.coins_cnt)
   2602     return TALER_amount_is_zero (&pc->validate_tokens.brutto);
   2603   GNUNET_assert (GNUNET_OK ==
   2604                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2605                                         &total_wire_fee));
   2606   for (unsigned int i = 0; i < pc->parse_pay.num_exchanges; i++)
   2607   {
   2608     if (GNUNET_OK !=
   2609         TALER_amount_cmp_currency (&total_wire_fee,
   2610                                    &pc->parse_pay.egs[i]->wire_fee))
   2611     {
   2612       GNUNET_break_op (0);
   2613       pay_end (pc,
   2614                TALER_MHD_reply_with_error (pc->connection,
   2615                                            MHD_HTTP_BAD_REQUEST,
   2616                                            TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2617                                            total_wire_fee.currency));
   2618       return false;
   2619     }
   2620     if (0 >
   2621         TALER_amount_add (&total_wire_fee,
   2622                           &total_wire_fee,
   2623                           &pc->parse_pay.egs[i]->wire_fee))
   2624     {
   2625       GNUNET_break (0);
   2626       pay_end (pc,
   2627                TALER_MHD_reply_with_error (
   2628                  pc->connection,
   2629                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2630                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED,
   2631                  "could not add exchange wire fee to total"));
   2632       return false;
   2633     }
   2634   }
   2635 
   2636   /**
   2637    * This loops calculates what are the deposit fee / total
   2638    * amount with fee / and wire fee, for all the coins.
   2639    */
   2640   GNUNET_assert (GNUNET_OK ==
   2641                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2642                                         &acc_fee));
   2643   GNUNET_assert (GNUNET_OK ==
   2644                  TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2645                                         &acc_amount));
   2646   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2647   {
   2648     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   2649 
   2650     GNUNET_assert (dc->found_in_db);
   2651     if ( (GNUNET_OK !=
   2652           TALER_amount_cmp_currency (&acc_fee,
   2653                                      &dc->deposit_fee)) ||
   2654          (GNUNET_OK !=
   2655           TALER_amount_cmp_currency (&acc_amount,
   2656                                      &dc->cdd.amount)) )
   2657     {
   2658       GNUNET_break_op (0);
   2659       pay_end (pc,
   2660                TALER_MHD_reply_with_error (
   2661                  pc->connection,
   2662                  MHD_HTTP_BAD_REQUEST,
   2663                  TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2664                  dc->deposit_fee.currency));
   2665       return false;
   2666     }
   2667     if ( (0 >
   2668           TALER_amount_add (&acc_fee,
   2669                             &dc->deposit_fee,
   2670                             &acc_fee)) ||
   2671          (0 >
   2672           TALER_amount_add (&acc_amount,
   2673                             &dc->cdd.amount,
   2674                             &acc_amount)) )
   2675     {
   2676       GNUNET_break (0);
   2677       /* Overflow in these amounts? Very strange. */
   2678       pay_end (pc,
   2679                TALER_MHD_reply_with_error (
   2680                  pc->connection,
   2681                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2682                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2683                  "Overflow adding up amounts"));
   2684       return false;
   2685     }
   2686     if (1 ==
   2687         TALER_amount_cmp (&dc->deposit_fee,
   2688                           &dc->cdd.amount))
   2689     {
   2690       GNUNET_break_op (0);
   2691       pay_end (pc,
   2692                TALER_MHD_reply_with_error (
   2693                  pc->connection,
   2694                  MHD_HTTP_BAD_REQUEST,
   2695                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT,
   2696                  "Deposit fees exceed coin's contribution"));
   2697       return false;
   2698     }
   2699   } /* end deposit loop */
   2700 
   2701   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2702               "Amount received from wallet: %s\n",
   2703               TALER_amount2s (&acc_amount));
   2704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2705               "Deposit fee for all coins: %s\n",
   2706               TALER_amount2s (&acc_fee));
   2707   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2708               "Total wire fee: %s\n",
   2709               TALER_amount2s (&total_wire_fee));
   2710   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2711               "Deposit fee limit for merchant: %s\n",
   2712               TALER_amount2s (&pc->validate_tokens.max_fee));
   2713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2714               "Total refunded amount: %s\n",
   2715               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2716 
   2717   /* Now compare exchange wire fee compared to what we are willing to pay */
   2718   if (GNUNET_YES !=
   2719       TALER_amount_cmp_currency (&total_wire_fee,
   2720                                  &acc_fee))
   2721   {
   2722     GNUNET_break (0);
   2723     pay_end (pc,
   2724              TALER_MHD_reply_with_error (
   2725                pc->connection,
   2726                MHD_HTTP_BAD_REQUEST,
   2727                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   2728                total_wire_fee.currency));
   2729     return false;
   2730   }
   2731 
   2732   /* add wire fee to the total fees */
   2733   if (0 >
   2734       TALER_amount_add (&acc_fee,
   2735                         &acc_fee,
   2736                         &total_wire_fee))
   2737   {
   2738     GNUNET_break (0);
   2739     pay_end (pc,
   2740              TALER_MHD_reply_with_error (
   2741                pc->connection,
   2742                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2743                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2744                "Overflow adding up amounts"));
   2745     return false;
   2746   }
   2747   if (-1 == TALER_amount_cmp (&pc->validate_tokens.max_fee,
   2748                               &acc_fee))
   2749   {
   2750     /**
   2751      * Sum of fees of *all* the different exchanges of all the coins are
   2752      * higher than the fixed limit that the merchant is willing to pay.  The
   2753      * difference must be paid by the customer.
   2754      */
   2755     struct TALER_Amount excess_fee;
   2756 
   2757     /* compute fee amount to be covered by customer */
   2758     GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
   2759                    TALER_amount_subtract (&excess_fee,
   2760                                           &acc_fee,
   2761                                           &pc->validate_tokens.max_fee));
   2762     /* add that to the total */
   2763     if (0 >
   2764         TALER_amount_add (&total_needed,
   2765                           &excess_fee,
   2766                           &pc->validate_tokens.brutto))
   2767     {
   2768       GNUNET_break (0);
   2769       pay_end (pc,
   2770                TALER_MHD_reply_with_error (
   2771                  pc->connection,
   2772                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   2773                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   2774                  "Overflow adding up amounts"));
   2775       return false;
   2776     }
   2777   }
   2778   else
   2779   {
   2780     /* Fees are fully covered by the merchant, all we require
   2781        is that the total payment is not below the contract's amount */
   2782     total_needed = pc->validate_tokens.brutto;
   2783   }
   2784 
   2785   /* Do not count refunds towards the payment */
   2786   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2787               "Subtracting total refunds from paid amount: %s\n",
   2788               TALER_amount2s (&pc->pay_transaction.total_refunded));
   2789   if (0 >
   2790       TALER_amount_subtract (&final_amount,
   2791                              &acc_amount,
   2792                              &pc->pay_transaction.total_refunded))
   2793   {
   2794     GNUNET_break (0);
   2795     pay_end (pc,
   2796              TALER_MHD_reply_with_error (
   2797                pc->connection,
   2798                MHD_HTTP_INTERNAL_SERVER_ERROR,
   2799                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS,
   2800                "refunded amount exceeds total payments"));
   2801     return false;
   2802   }
   2803 
   2804   if (-1 == TALER_amount_cmp (&final_amount,
   2805                               &total_needed))
   2806   {
   2807     /* acc_amount < total_needed */
   2808     if (-1 < TALER_amount_cmp (&acc_amount,
   2809                                &total_needed))
   2810     {
   2811       GNUNET_break_op (0);
   2812       pay_end (pc,
   2813                TALER_MHD_reply_with_error (
   2814                  pc->connection,
   2815                  MHD_HTTP_PAYMENT_REQUIRED,
   2816                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED,
   2817                  "contract not paid up due to refunds"));
   2818       return false;
   2819     }
   2820     if (-1 < TALER_amount_cmp (&acc_amount,
   2821                                &pc->validate_tokens.brutto))
   2822     {
   2823       GNUNET_break_op (0);
   2824       pay_end (pc,
   2825                TALER_MHD_reply_with_error (
   2826                  pc->connection,
   2827                  MHD_HTTP_BAD_REQUEST,
   2828                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES,
   2829                  "contract not paid up due to fees (client may have calculated them badly)"));
   2830       return false;
   2831     }
   2832     GNUNET_break_op (0);
   2833     pay_end (pc,
   2834              TALER_MHD_reply_with_error (
   2835                pc->connection,
   2836                MHD_HTTP_BAD_REQUEST,
   2837                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT,
   2838                "payment insufficient"));
   2839     return false;
   2840   }
   2841   return true;
   2842 }
   2843 
   2844 
   2845 /**
   2846  * Execute the DB transaction.  If required (from
   2847  * soft/serialization errors), the transaction can be
   2848  * restarted here.
   2849  *
   2850  * @param[in,out] pc payment context to transact
   2851  */
   2852 static void
   2853 phase_execute_pay_transaction (struct PayContext *pc)
   2854 {
   2855   struct TMH_HandlerContext *hc = pc->hc;
   2856   const char *instance_id = hc->instance->settings.id;
   2857 
   2858   if (pc->batch_deposits.got_451)
   2859   {
   2860     pc->phase = PP_FAIL_LEGAL_REASONS;
   2861     return;
   2862   }
   2863   /* Avoid re-trying transactions on soft errors forever! */
   2864   if (pc->pay_transaction.retry_counter++ > MAX_RETRIES)
   2865   {
   2866     GNUNET_break (0);
   2867     pay_end (pc,
   2868              TALER_MHD_reply_with_error (pc->connection,
   2869                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2870                                          TALER_EC_GENERIC_DB_SOFT_FAILURE,
   2871                                          NULL));
   2872     return;
   2873   }
   2874 
   2875   /* Initialize some amount accumulators
   2876      (used in check_coin_paid(), check_coin_refunded()
   2877      and check_payment_sufficient()). */
   2878   GNUNET_break (GNUNET_OK ==
   2879                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2880                                        &pc->pay_transaction.total_paid));
   2881   GNUNET_break (GNUNET_OK ==
   2882                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2883                                        &pc->pay_transaction.total_fees_paid));
   2884   GNUNET_break (GNUNET_OK ==
   2885                 TALER_amount_set_zero (pc->validate_tokens.brutto.currency,
   2886                                        &pc->pay_transaction.total_refunded));
   2887   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   2888     pc->parse_pay.dc[i].found_in_db = false;
   2889   pc->pay_transaction.pending = pc->parse_pay.coins_cnt;
   2890 
   2891   /* First, try to see if we have all we need already done */
   2892   TMH_db->preflight (TMH_db->cls);
   2893   if (GNUNET_OK !=
   2894       TMH_db->start (TMH_db->cls,
   2895                      "run pay"))
   2896   {
   2897     GNUNET_break (0);
   2898     pay_end (pc,
   2899              TALER_MHD_reply_with_error (pc->connection,
   2900                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
   2901                                          TALER_EC_GENERIC_DB_START_FAILED,
   2902                                          NULL));
   2903     return;
   2904   }
   2905 
   2906   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   2907   {
   2908     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   2909     enum GNUNET_DB_QueryStatus qs;
   2910 
   2911     /* Insert used token into database, the unique constraint will
   2912        case an error if this token was used before. */
   2913     qs = TMH_db->insert_spent_token (TMH_db->cls,
   2914                                      &pc->check_contract.h_contract_terms,
   2915                                      &tuc->h_issue,
   2916                                      &tuc->pub,
   2917                                      &tuc->sig,
   2918                                      &tuc->unblinded_sig);
   2919 
   2920     switch (qs)
   2921     {
   2922     case GNUNET_DB_STATUS_SOFT_ERROR:
   2923       TMH_db->rollback (TMH_db->cls);
   2924       return; /* do it again */
   2925     case GNUNET_DB_STATUS_HARD_ERROR:
   2926       /* Always report on hard error as well to enable diagnostics */
   2927       TMH_db->rollback (TMH_db->cls);
   2928       pay_end (pc,
   2929                TALER_MHD_reply_with_error (pc->connection,
   2930                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2931                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   2932                                            "insert used token"));
   2933       return;
   2934     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   2935       /* UNIQUE constraint violation, meaning this token was already used. */
   2936       TMH_db->rollback (TMH_db->cls);
   2937       pay_end (pc,
   2938                TALER_MHD_reply_with_error (pc->connection,
   2939                                            MHD_HTTP_CONFLICT,
   2940                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID,
   2941                                            NULL));
   2942       return;
   2943     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   2944       /* Good, proceed! */
   2945       break;
   2946     }
   2947   } /* for all tokens */
   2948 
   2949   {
   2950     enum GNUNET_DB_QueryStatus qs;
   2951 
   2952     /* Check if some of these coins already succeeded for _this_ contract.  */
   2953     qs = TMH_db->lookup_deposits (TMH_db->cls,
   2954                                   instance_id,
   2955                                   &pc->check_contract.h_contract_terms,
   2956                                   &check_coin_paid,
   2957                                   pc);
   2958     if (0 > qs)
   2959     {
   2960       TMH_db->rollback (TMH_db->cls);
   2961       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2962         return; /* do it again */
   2963       /* Always report on hard error as well to enable diagnostics */
   2964       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   2965       pay_end (pc,
   2966                TALER_MHD_reply_with_error (pc->connection,
   2967                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   2968                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   2969                                            "lookup deposits"));
   2970       return;
   2971     }
   2972     if (pc->pay_transaction.deposit_currency_mismatch)
   2973     {
   2974       TMH_db->rollback (TMH_db->cls);
   2975       GNUNET_break_op (0);
   2976       pay_end (pc,
   2977                TALER_MHD_reply_with_error (
   2978                  pc->connection,
   2979                  MHD_HTTP_BAD_REQUEST,
   2980                  TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   2981                  pc->validate_tokens.brutto.currency));
   2982       return;
   2983     }
   2984   }
   2985 
   2986   {
   2987     enum GNUNET_DB_QueryStatus qs;
   2988 
   2989     /* Check if we refunded some of the coins */
   2990     qs = TMH_db->lookup_refunds (TMH_db->cls,
   2991                                  instance_id,
   2992                                  &pc->check_contract.h_contract_terms,
   2993                                  &check_coin_refunded,
   2994                                  pc);
   2995     if (0 > qs)
   2996     {
   2997       TMH_db->rollback (TMH_db->cls);
   2998       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   2999         return; /* do it again */
   3000       /* Always report on hard error as well to enable diagnostics */
   3001       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   3002       pay_end (pc,
   3003                TALER_MHD_reply_with_error (pc->connection,
   3004                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3005                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   3006                                            "lookup refunds"));
   3007       return;
   3008     }
   3009     if (pc->pay_transaction.refund_currency_mismatch)
   3010     {
   3011       TMH_db->rollback (TMH_db->cls);
   3012       pay_end (pc,
   3013                TALER_MHD_reply_with_error (pc->connection,
   3014                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3015                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
   3016                                            "refund currency in database does not match order currency"));
   3017       return;
   3018     }
   3019   }
   3020 
   3021   /* Check if there are coins that still need to be processed */
   3022   if (0 != pc->pay_transaction.pending)
   3023   {
   3024     /* we made no DB changes, so we can just rollback */
   3025     TMH_db->rollback (TMH_db->cls);
   3026     /* Ok, we need to first go to the network to process more coins.
   3027        We that interaction in *tiny* transactions (hence the rollback
   3028        above). */
   3029     pc->phase = PP_BATCH_DEPOSITS;
   3030     return;
   3031   }
   3032 
   3033   /* 0 == pc->pay_transaction.pending: all coins processed, let's see if that was enough */
   3034   if (! check_payment_sufficient (pc))
   3035   {
   3036     /* check_payment_sufficient() will have queued an error already.
   3037        We need to still abort the transaction. */
   3038     TMH_db->rollback (TMH_db->cls);
   3039     return;
   3040   }
   3041   /* Payment succeeded, save in database */
   3042   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3043               "Order `%s' (%s) was fully paid\n",
   3044               pc->order_id,
   3045               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   3046   {
   3047     enum GNUNET_DB_QueryStatus qs;
   3048 
   3049     qs = TMH_db->mark_contract_paid (TMH_db->cls,
   3050                                      instance_id,
   3051                                      &pc->check_contract.h_contract_terms,
   3052                                      pc->parse_pay.session_id,
   3053                                      pc->parse_wallet_data.choice_index);
   3054     if (qs < 0)
   3055     {
   3056       TMH_db->rollback (TMH_db->cls);
   3057       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3058         return; /* do it again */
   3059       GNUNET_break (0);
   3060       pay_end (pc,
   3061                TALER_MHD_reply_with_error (pc->connection,
   3062                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3063                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   3064                                            "mark contract paid"));
   3065       return;
   3066     }
   3067     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3068                 "Marked contract paid returned %d\n",
   3069                 (int) qs);
   3070 
   3071     if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
   3072          (0 < pc->compute_money_pots.num_pots) )
   3073     {
   3074       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3075                   "Incrementing %u money pots by %s\n",
   3076                   pc->compute_money_pots.num_pots,
   3077                   TALER_amount2s (&pc->compute_money_pots.increments[0]));
   3078       qs = TMH_db->increment_money_pots (TMH_db->cls,
   3079                                          instance_id,
   3080                                          pc->compute_money_pots.num_pots,
   3081                                          pc->compute_money_pots.pots,
   3082                                          pc->compute_money_pots.increments);
   3083       switch (qs)
   3084       {
   3085       case GNUNET_DB_STATUS_SOFT_ERROR:
   3086         TMH_db->rollback (TMH_db->cls);
   3087         return; /* do it again */
   3088       case GNUNET_DB_STATUS_HARD_ERROR:
   3089         /* Always report on hard error as well to enable diagnostics */
   3090         TMH_db->rollback (TMH_db->cls);
   3091         pay_end (pc,
   3092                  TALER_MHD_reply_with_error (pc->connection,
   3093                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
   3094                                              TALER_EC_GENERIC_DB_STORE_FAILED,
   3095                                              "increment_money_pots"));
   3096         return;
   3097       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3098         /* strange */
   3099         GNUNET_break (0);
   3100         break;
   3101       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3102         /* Good, proceed! */
   3103         break;
   3104       }
   3105 
   3106     }
   3107 
   3108 
   3109   }
   3110 
   3111 
   3112   {
   3113     const struct TALER_MERCHANT_ContractChoice *choice =
   3114       &pc->check_contract.contract_terms->details.v1
   3115       .choices[pc->parse_wallet_data.choice_index];
   3116 
   3117     for (size_t i = 0; i<pc->output_tokens_len; i++)
   3118     {
   3119       unsigned int output_index;
   3120       enum TALER_MERCHANT_ContractOutputType type;
   3121 
   3122       output_index = pc->output_tokens[i].output_index;
   3123       GNUNET_assert (output_index < choice->outputs_len);
   3124       type = choice->outputs[output_index].type;
   3125 
   3126       switch (type)
   3127       {
   3128       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3129         /* Well, good luck getting here */
   3130         GNUNET_break (0);
   3131         pay_end (pc,
   3132                  TALER_MHD_reply_with_error (pc->connection,
   3133                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
   3134                                              TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3135                                              "invalid output type"));
   3136         break;
   3137       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3138         /* We skip output tokens of donation receipts here, as they are handled in the
   3139          * phase_final_output_token_processing() callback from donau */
   3140         break;
   3141       case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3142         struct SignedOutputToken *output =
   3143           &pc->output_tokens[i];
   3144         enum GNUNET_DB_QueryStatus qs;
   3145 
   3146         qs = TMH_db->insert_issued_token (TMH_db->cls,
   3147                                           &pc->check_contract.h_contract_terms,
   3148                                           &output->h_issue,
   3149                                           &output->sig);
   3150         switch (qs)
   3151         {
   3152         case GNUNET_DB_STATUS_HARD_ERROR:
   3153           TMH_db->rollback (TMH_db->cls);
   3154           GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   3155           pay_end (pc,
   3156                    TALER_MHD_reply_with_error (pc->connection,
   3157                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3158                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   3159                                                "insert output token"));
   3160           return;
   3161         case GNUNET_DB_STATUS_SOFT_ERROR:
   3162           /* Serialization failure, retry */
   3163           TMH_db->rollback (TMH_db->cls);
   3164           return;
   3165         case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3166           /* UNIQUE constraint violation, meaning this token was already used. */
   3167           TMH_db->rollback (TMH_db->cls);
   3168           pay_end (pc,
   3169                    TALER_MHD_reply_with_error (pc->connection,
   3170                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3171                                                TALER_EC_GENERIC_DB_STORE_FAILED,
   3172                                                "duplicate output token"));
   3173           return;
   3174         case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3175           break;
   3176         }
   3177         break;
   3178       }
   3179     }
   3180   }
   3181 
   3182   TMH_notify_order_change (hc->instance,
   3183                            TMH_OSF_CLAIMED | TMH_OSF_PAID,
   3184                            pc->check_contract.contract_terms->timestamp,
   3185                            pc->check_contract.order_serial);
   3186   {
   3187     enum GNUNET_DB_QueryStatus qs;
   3188     json_t *jhook;
   3189 
   3190     jhook = GNUNET_JSON_PACK (
   3191       GNUNET_JSON_pack_object_incref ("contract_terms",
   3192                                       pc->check_contract.contract_terms_json),
   3193       GNUNET_JSON_pack_string ("order_id",
   3194                                pc->order_id)
   3195       );
   3196     GNUNET_assert (NULL != jhook);
   3197     qs = TMH_trigger_webhook (pc->hc->instance->settings.id,
   3198                               "pay",
   3199                               jhook);
   3200     json_decref (jhook);
   3201     if (qs < 0)
   3202     {
   3203       TMH_db->rollback (TMH_db->cls);
   3204       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3205         return; /* do it again */
   3206       GNUNET_break (0);
   3207       pay_end (pc,
   3208                TALER_MHD_reply_with_error (pc->connection,
   3209                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3210                                            TALER_EC_GENERIC_DB_STORE_FAILED,
   3211                                            "failed to trigger webhooks"));
   3212       return;
   3213     }
   3214   }
   3215   {
   3216     enum GNUNET_DB_QueryStatus qs;
   3217 
   3218     /* Now commit! */
   3219     qs = TMH_db->commit (TMH_db->cls);
   3220     if (0 > qs)
   3221     {
   3222       /* commit failed */
   3223       TMH_db->rollback (TMH_db->cls);
   3224       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   3225         return; /* do it again */
   3226       GNUNET_break (0);
   3227       pay_end (pc,
   3228                TALER_MHD_reply_with_error (pc->connection,
   3229                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3230                                            TALER_EC_GENERIC_DB_COMMIT_FAILED,
   3231                                            NULL));
   3232       return;
   3233     }
   3234   }
   3235   pc->phase++;
   3236 }
   3237 
   3238 
   3239 /**
   3240  * Ensures that the expected number of tokens for a @e key
   3241  * are provided as inputs and have valid signatures.
   3242  *
   3243  * @param[in,out] pc payment context we are processing
   3244  * @param family family the tokens should be from
   3245  * @param index number of the input we are handling
   3246  * @param expected_num number of tokens expected
   3247  * @return #GNUNET_YES on success
   3248  */
   3249 static enum GNUNET_GenericReturnValue
   3250 find_valid_input_tokens (
   3251   struct PayContext *pc,
   3252   const struct TALER_MERCHANT_ContractTokenFamily *family,
   3253   unsigned int index,
   3254   unsigned int expected_num)
   3255 {
   3256   unsigned int num_validated = 0;
   3257   struct GNUNET_TIME_Timestamp now
   3258     = GNUNET_TIME_timestamp_get ();
   3259   const struct TALER_MERCHANT_ContractTokenFamilyKey *kig = NULL;
   3260 
   3261   for (unsigned int j = 0; j < expected_num; j++)
   3262   {
   3263     struct TokenUseConfirmation *tuc
   3264       = &pc->parse_pay.tokens[index + j];
   3265     const struct TALER_MERCHANT_ContractTokenFamilyKey *key = NULL;
   3266 
   3267     for (unsigned int i = 0; i<family->keys_len; i++)
   3268     {
   3269       const struct TALER_MERCHANT_ContractTokenFamilyKey *ki
   3270         = &family->keys[i];
   3271 
   3272       if (0 ==
   3273           GNUNET_memcmp (&ki->pub.public_key->pub_key_hash,
   3274                          &tuc->h_issue.hash))
   3275       {
   3276         if (GNUNET_TIME_timestamp_cmp (ki->valid_after,
   3277                                        >,
   3278                                        now) ||
   3279             GNUNET_TIME_timestamp_cmp (ki->valid_before,
   3280                                        <=,
   3281                                        now))
   3282         {
   3283           /* We have a match, but not in the current validity period */
   3284           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3285                       "Public key %s currently not valid\n",
   3286                       GNUNET_h2s (&ki->pub.public_key->pub_key_hash));
   3287           kig = ki;
   3288           continue;
   3289         }
   3290         key = ki;
   3291         break;
   3292       }
   3293     }
   3294     if (NULL == key)
   3295     {
   3296       if (NULL != kig)
   3297       {
   3298         char start_str[128];
   3299         char end_str[128];
   3300         char emsg[350];
   3301 
   3302         GNUNET_snprintf (start_str,
   3303                          sizeof (start_str),
   3304                          "%s",
   3305                          GNUNET_STRINGS_timestamp_to_string (kig->valid_after));
   3306         GNUNET_snprintf (end_str,
   3307                          sizeof (end_str),
   3308                          "%s",
   3309                          GNUNET_STRINGS_timestamp_to_string (kig->valid_before))
   3310         ;
   3311         /* FIXME: use more specific EC */
   3312         GNUNET_snprintf (emsg,
   3313                          sizeof (emsg),
   3314                          "Token is only valid from %s to %s",
   3315                          start_str,
   3316                          end_str);
   3317         pay_end (pc,
   3318                  TALER_MHD_reply_with_error (
   3319                    pc->connection,
   3320                    MHD_HTTP_GONE,
   3321                    TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   3322                    emsg));
   3323         return GNUNET_NO;
   3324       }
   3325       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3326                   "Input token supplied for public key %s that is not acceptable\n",
   3327                   GNUNET_h2s (&tuc->h_issue.hash));
   3328       GNUNET_break_op (0);
   3329       pay_end (pc,
   3330                TALER_MHD_reply_with_error (
   3331                  pc->connection,
   3332                  MHD_HTTP_BAD_REQUEST,
   3333                  TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN,
   3334                  NULL));
   3335       return GNUNET_NO;
   3336     }
   3337     if (GNUNET_OK !=
   3338         TALER_token_issue_verify (&tuc->pub,
   3339                                   &key->pub,
   3340                                   &tuc->unblinded_sig))
   3341     {
   3342       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3343                   "Input token for public key with valid_after "
   3344                   "`%s' has invalid issue signature\n",
   3345                   GNUNET_TIME_timestamp2s (key->valid_after));
   3346       GNUNET_break (0);
   3347       pay_end (pc,
   3348                TALER_MHD_reply_with_error (
   3349                  pc->connection,
   3350                  MHD_HTTP_BAD_REQUEST,
   3351                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID,
   3352                  NULL));
   3353       return GNUNET_NO;
   3354     }
   3355 
   3356     if (GNUNET_OK !=
   3357         TALER_wallet_token_use_verify (&pc->check_contract.h_contract_terms,
   3358                                        &pc->parse_wallet_data.h_wallet_data,
   3359                                        &tuc->pub,
   3360                                        &tuc->sig))
   3361     {
   3362       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3363                   "Input token for public key with valid_before "
   3364                   "`%s' has invalid use signature\n",
   3365                   GNUNET_TIME_timestamp2s (key->valid_before));
   3366       GNUNET_break (0);
   3367       pay_end (pc,
   3368                TALER_MHD_reply_with_error (
   3369                  pc->connection,
   3370                  MHD_HTTP_BAD_REQUEST,
   3371                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID,
   3372                  NULL));
   3373       return GNUNET_NO;
   3374     }
   3375 
   3376     num_validated++;
   3377   }
   3378 
   3379   if (num_validated != expected_num)
   3380   {
   3381     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3382                 "Expected %d tokens for family %s, but found %d\n",
   3383                 expected_num,
   3384                 family->slug,
   3385                 num_validated);
   3386     GNUNET_break (0);
   3387     pay_end (pc,
   3388              TALER_MHD_reply_with_error (
   3389                pc->connection,
   3390                MHD_HTTP_BAD_REQUEST,
   3391                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH,
   3392                NULL));
   3393     return GNUNET_NO;
   3394   }
   3395   return GNUNET_YES;
   3396 }
   3397 
   3398 
   3399 /**
   3400  * Check if an output token of the given @a tfk is mandatory, or if
   3401  * wallets are allowed to simply not support it and still proceed.
   3402  *
   3403  * @param tfk token family kind to check
   3404  * @return true if such outputs are mandatory and wallets must supply
   3405  *  the corresponding blinded input
   3406  */
   3407 /* FIXME: this function belongs into a lower-level lib! */
   3408 static bool
   3409 test_tfk_mandatory (enum TALER_MERCHANTDB_TokenFamilyKind tfk)
   3410 {
   3411   switch (tfk)
   3412   {
   3413   case TALER_MERCHANTDB_TFK_Discount:
   3414     return false;
   3415   case TALER_MERCHANTDB_TFK_Subscription:
   3416     return true;
   3417   }
   3418   GNUNET_break (0);
   3419   return false;
   3420 }
   3421 
   3422 
   3423 /**
   3424  * Sign the tokens provided by the wallet for a particular @a key.
   3425  *
   3426  * @param[in,out] pc reference for payment we are processing
   3427  * @param key token family data
   3428  * @param priv private key to use to sign with
   3429  * @param mandatory true if the token must exist, if false
   3430  *        and the client did not provide an envelope, that's OK and
   3431  *        we just also skimp on the signature
   3432  * @param index offset in the token envelope array (from other families)
   3433  * @param expected_num number of tokens of this type that we should create
   3434  * @return #GNUNET_NO on failure
   3435  *         #GNUNET_OK on success
   3436  */
   3437 static enum GNUNET_GenericReturnValue
   3438 sign_token_envelopes (
   3439   struct PayContext *pc,
   3440   const struct TALER_MERCHANT_ContractTokenFamilyKey *key,
   3441   const struct TALER_TokenIssuePrivateKey *priv,
   3442   bool mandatory,
   3443   unsigned int index,
   3444   unsigned int expected_num)
   3445 {
   3446   unsigned int num_signed = 0;
   3447 
   3448   for (unsigned int j = 0; j<expected_num; j++)
   3449   {
   3450     unsigned int pos = index + j;
   3451     const struct TokenEnvelope *env
   3452       = &pc->parse_wallet_data.token_envelopes[pos];
   3453     struct SignedOutputToken *output
   3454       = &pc->output_tokens[pos];
   3455 
   3456     if ( (pos >= pc->parse_wallet_data.token_envelopes_cnt) ||
   3457          (pos >= pc->output_tokens_len) )
   3458     {
   3459       GNUNET_assert (0); /* this should not happen */
   3460       return GNUNET_NO;
   3461     }
   3462     if (NULL == env->blinded_token.blinded_pub)
   3463     {
   3464       if (! mandatory)
   3465         continue;
   3466 
   3467       /* mandatory token families require a token envelope. */
   3468       GNUNET_break_op (0);
   3469       pay_end (pc,
   3470                TALER_MHD_reply_with_error (
   3471                  pc->connection,
   3472                  MHD_HTTP_BAD_REQUEST,
   3473                  TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3474                  "Token envelope for mandatory token family missing"));
   3475       return GNUNET_NO;
   3476     }
   3477     TALER_token_issue_sign (priv,
   3478                             &env->blinded_token,
   3479                             &output->sig);
   3480     output->h_issue.hash
   3481       = key->pub.public_key->pub_key_hash;
   3482     num_signed++;
   3483   }
   3484 
   3485   if (mandatory &&
   3486       (num_signed != expected_num) )
   3487   {
   3488     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3489                 "Expected %d token envelopes for public key with valid_after "
   3490                 "'%s', but found %d\n",
   3491                 expected_num,
   3492                 GNUNET_TIME_timestamp2s (key->valid_after),
   3493                 num_signed);
   3494     GNUNET_break (0);
   3495     pay_end (pc,
   3496              TALER_MHD_reply_with_error (
   3497                pc->connection,
   3498                MHD_HTTP_BAD_REQUEST,
   3499                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH,
   3500                NULL));
   3501     return GNUNET_NO;
   3502   }
   3503 
   3504   return GNUNET_OK;
   3505 }
   3506 
   3507 
   3508 /**
   3509  * Find the family entry for the family of the given @a slug
   3510  * in @a pc.
   3511  *
   3512  * @param[in] pc payment context to search
   3513  * @param slug slug to search for
   3514  * @return NULL if @a slug was not found
   3515  */
   3516 static const struct TALER_MERCHANT_ContractTokenFamily *
   3517 find_family (const struct PayContext *pc,
   3518              const char *slug)
   3519 {
   3520   for (unsigned int i = 0;
   3521        i < pc->check_contract.contract_terms->details.v1.token_authorities_len;
   3522        i++)
   3523   {
   3524     const struct TALER_MERCHANT_ContractTokenFamily *tfi
   3525       = &pc->check_contract.contract_terms->details.v1.token_authorities[i];
   3526 
   3527     if (0 == strcmp (tfi->slug,
   3528                      slug))
   3529     {
   3530       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3531                   "Token family %s found with %u keys\n",
   3532                   slug,
   3533                   tfi->keys_len);
   3534       return tfi;
   3535     }
   3536   }
   3537   return NULL;
   3538 }
   3539 
   3540 
   3541 /**
   3542  * Handle contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN.
   3543  * Looks up the token family, loads the matching private key,
   3544  * and signs the corresponding token envelopes from the wallet.
   3545  *
   3546  * @param pc context for the pay request
   3547  * @param output contract output we need to process
   3548  * @param output_index index of this output in the contract's outputs array
   3549  * @return #GNUNET_OK on success, #GNUNET_NO if an error was encountered
   3550  */
   3551 static enum GNUNET_GenericReturnValue
   3552 handle_output_token (struct PayContext *pc,
   3553                      const struct TALER_MERCHANT_ContractOutput *output,
   3554                      unsigned int output_index)
   3555 {
   3556   const struct TALER_MERCHANT_ContractTokenFamily *family;
   3557   struct TALER_MERCHANT_ContractTokenFamilyKey *key;
   3558   struct TALER_MERCHANTDB_TokenFamilyKeyDetails details;
   3559   enum GNUNET_DB_QueryStatus qs;
   3560   bool mandatory;
   3561 
   3562   /* Locate token family in the contract.
   3563      This should ever fail as this invariant should
   3564      have been checked when the contract was created. */
   3565   family = find_family (pc,
   3566                         output->details.token.token_family_slug);
   3567   if (NULL == family)
   3568   {
   3569     /* This "should never happen", so treat it as an internal error */
   3570     GNUNET_break (0);
   3571     pay_end (pc,
   3572              TALER_MHD_reply_with_error (
   3573                pc->connection,
   3574                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3575                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3576                "token family not found in order"));
   3577     return GNUNET_SYSERR;
   3578   }
   3579 
   3580   /* Check the key_index field from the output. */
   3581   if (output->details.token.key_index >= family->keys_len)
   3582   {
   3583     /* Also "should never happen", contract was presumably validated on insert */
   3584     GNUNET_break (0);
   3585     pay_end (pc,
   3586              TALER_MHD_reply_with_error (
   3587                pc->connection,
   3588                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3589                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3590                "key index invalid for token family"));
   3591     return GNUNET_SYSERR;
   3592   }
   3593 
   3594   /* Pick the correct key inside that family. */
   3595   key = &family->keys[output->details.token.key_index];
   3596 
   3597   /* Fetch the private key from the DB for the merchant instance and
   3598    * this particular family/time interval. */
   3599   qs = TMH_db->lookup_token_family_key (
   3600     TMH_db->cls,
   3601     pc->hc->instance->settings.id,
   3602     family->slug,
   3603     pc->check_contract.contract_terms->timestamp,
   3604     pc->check_contract.contract_terms->pay_deadline,
   3605     &details);
   3606   switch (qs)
   3607   {
   3608   case GNUNET_DB_STATUS_HARD_ERROR:
   3609   case GNUNET_DB_STATUS_SOFT_ERROR:
   3610     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3611                 "Database error looking up token-family key for %s\n",
   3612                 family->slug);
   3613     GNUNET_break (0);
   3614     pay_end (pc,
   3615              TALER_MHD_reply_with_error (
   3616                pc->connection,
   3617                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3618                TALER_EC_GENERIC_DB_FETCH_FAILED,
   3619                NULL));
   3620     return GNUNET_NO;
   3621   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   3622     GNUNET_log (
   3623       GNUNET_ERROR_TYPE_ERROR,
   3624       "Token-family key for %s not found at [%llu,%llu]\n",
   3625       family->slug,
   3626       (unsigned long long)
   3627       pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us,
   3628       (unsigned long long)
   3629       pc->check_contract.contract_terms->pay_deadline.abs_time.abs_value_us
   3630       );
   3631     GNUNET_break (0);
   3632     pay_end (pc,
   3633              TALER_MHD_reply_with_error (
   3634                pc->connection,
   3635                MHD_HTTP_NOT_FOUND,
   3636                TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN,
   3637                family->slug));
   3638     return GNUNET_NO;
   3639 
   3640   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   3641     break;
   3642   }
   3643   GNUNET_assert (NULL != details.priv.private_key);
   3644   GNUNET_free (details.token_family.slug);
   3645   GNUNET_free (details.token_family.name);
   3646   GNUNET_free (details.token_family.description);
   3647   json_decref (details.token_family.description_i18n);
   3648   GNUNET_CRYPTO_blind_sign_pub_decref (details.pub.public_key);
   3649   GNUNET_free (details.token_family.cipher_spec);
   3650 
   3651   /* Depending on the token family, decide if the token envelope
   3652    * is mandatory or optional.  (Simplified logic here: adapt as needed.) */
   3653   mandatory = test_tfk_mandatory (details.token_family.kind);
   3654   /* Actually sign the number of token envelopes specified in 'count'.
   3655    * 'output_index' is the offset into the parse_wallet_data arrays.  */
   3656   if (GNUNET_OK !=
   3657       sign_token_envelopes (pc,
   3658                             key,
   3659                             &details.priv,
   3660                             mandatory,
   3661                             output_index,
   3662                             output->details.token.count))
   3663   {
   3664     /* sign_token_envelopes() already queued up an error via pay_end() */
   3665     GNUNET_break_op (0);
   3666     return GNUNET_NO;
   3667   }
   3668   GNUNET_CRYPTO_blind_sign_priv_decref (details.priv.private_key);
   3669   return GNUNET_OK;
   3670 }
   3671 
   3672 
   3673 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3674 /**
   3675  * Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT.
   3676  * For now, this does nothing and simply returns #GNUNET_OK.
   3677  *
   3678  * @param pc context for the pay request
   3679  * @param output the contract output describing the donation receipt requirement
   3680  * @return #GNUNET_OK on success,
   3681  *         #GNUNET_NO if an error was already queued
   3682  */
   3683 static enum GNUNET_GenericReturnValue
   3684 handle_output_donation_receipt (
   3685   struct PayContext *pc,
   3686   const struct TALER_MERCHANT_ContractOutput *output)
   3687 {
   3688   enum GNUNET_GenericReturnValue ret;
   3689 
   3690   ret = DONAU_get_donation_amount_from_bkps (
   3691     pc->parse_wallet_data.donau_keys,
   3692     pc->parse_wallet_data.bkps,
   3693     pc->parse_wallet_data.num_bkps,
   3694     pc->parse_wallet_data.donau.donation_year,
   3695     &pc->parse_wallet_data.donation_amount);
   3696   switch (ret)
   3697   {
   3698   case GNUNET_SYSERR:
   3699     GNUNET_break (0);
   3700     pay_end (pc,
   3701              TALER_MHD_reply_with_error (
   3702                pc->connection,
   3703                MHD_HTTP_INTERNAL_SERVER_ERROR,
   3704                TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3705                NULL));
   3706     return GNUNET_NO;
   3707   case GNUNET_NO:
   3708     GNUNET_break_op (0);
   3709     pay_end (pc,
   3710              TALER_MHD_reply_with_error (
   3711                pc->connection,
   3712                MHD_HTTP_BAD_REQUEST,
   3713                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3714                "inconsistent bkps / donau keys"));
   3715     return GNUNET_NO;
   3716   case GNUNET_OK:
   3717     break;
   3718   }
   3719 
   3720   if (GNUNET_OK !=
   3721       TALER_amount_cmp_currency (&pc->parse_wallet_data.donation_amount,
   3722                                  &output->details.donation_receipt.amount))
   3723   {
   3724     GNUNET_break_op (0);
   3725     pay_end (pc,
   3726              TALER_MHD_reply_with_error (
   3727                pc->connection,
   3728                MHD_HTTP_BAD_REQUEST,
   3729                TALER_EC_GENERIC_CURRENCY_MISMATCH,
   3730                output->details.donation_receipt.amount.currency));
   3731     return GNUNET_NO;
   3732   }
   3733 
   3734   if (0 !=
   3735       TALER_amount_cmp (&pc->parse_wallet_data.donation_amount,
   3736                         &output->details.donation_receipt.amount))
   3737   {
   3738     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3739                 "Wallet amount: %s\n",
   3740                 TALER_amount2s (&pc->parse_wallet_data.donation_amount));
   3741     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3742                 "Donation receipt amount: %s\n",
   3743                 TALER_amount2s (&output->details.donation_receipt.amount));
   3744     GNUNET_break_op (0);
   3745     pay_end (pc,
   3746              TALER_MHD_reply_with_error (
   3747                pc->connection,
   3748                MHD_HTTP_CONFLICT,
   3749                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3750                "donation amount mismatch"));
   3751     return GNUNET_NO;
   3752   }
   3753   {
   3754     struct TALER_Amount receipts_to_date;
   3755 
   3756     if (0 >
   3757         TALER_amount_add (&receipts_to_date,
   3758                           &pc->parse_wallet_data.charity_receipts_to_date,
   3759                           &pc->parse_wallet_data.donation_amount))
   3760     {
   3761       GNUNET_break (0);
   3762       pay_end (pc,
   3763                TALER_MHD_reply_with_error (pc->connection,
   3764                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
   3765                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   3766                                            "adding donation amount"));
   3767       return GNUNET_NO;
   3768     }
   3769 
   3770     if (1 ==
   3771         TALER_amount_cmp (&receipts_to_date,
   3772                           &pc->parse_wallet_data.charity_max_per_year))
   3773     {
   3774       GNUNET_break_op (0);
   3775       pay_end (pc,
   3776                TALER_MHD_reply_with_error (pc->connection,
   3777                                            MHD_HTTP_CONFLICT,
   3778                                            TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH,
   3779                                            "donation limit exceeded"));
   3780       return GNUNET_NO;
   3781     }
   3782     pc->parse_wallet_data.charity_receipts_to_date = receipts_to_date;
   3783   }
   3784   return GNUNET_OK;
   3785 }
   3786 
   3787 
   3788 #endif /* HAVE_DONAU_DONAU_SERVICE_H */
   3789 
   3790 
   3791 /**
   3792  * Count tokens produced by an output.
   3793  *
   3794  * @param pc pay context
   3795  * @param output output to consider
   3796  * @returns number of output tokens
   3797  */
   3798 static unsigned int
   3799 count_output_tokens (const struct PayContext *pc,
   3800                      const struct TALER_MERCHANT_ContractOutput *output)
   3801 {
   3802   switch (output->type)
   3803   {
   3804   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3805     GNUNET_assert (0);
   3806     break;
   3807   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3808     return output->details.token.count;
   3809   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3810 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3811     return pc->parse_wallet_data.num_bkps;
   3812 #else
   3813     return 0;
   3814 #endif
   3815   }
   3816   /* Not reached. */
   3817   GNUNET_assert (0);
   3818 }
   3819 
   3820 
   3821 /**
   3822  * Validate tokens and token envelopes. First, we check if all tokens listed
   3823  * in the 'inputs' array of the selected choice are present in the 'tokens'
   3824  * array of the request. Then, we validate the signatures of each provided
   3825  * token.
   3826  *
   3827  * @param[in,out] pc context we use to handle the payment
   3828  */
   3829 static void
   3830 phase_validate_tokens (struct PayContext *pc)
   3831 {
   3832   /* We haven't seen a donau output yet. */
   3833   pc->validate_tokens.donau_output_index = -1;
   3834 
   3835   switch (pc->check_contract.contract_terms->version)
   3836   {
   3837   case TALER_MERCHANT_CONTRACT_VERSION_0:
   3838     /* No tokens to validate */
   3839     pc->phase = PP_COMPUTE_MONEY_POTS;
   3840     pc->validate_tokens.max_fee
   3841       = pc->check_contract.contract_terms->details.v0.max_fee;
   3842     pc->validate_tokens.brutto
   3843       = pc->check_contract.contract_terms->details.v0.brutto;
   3844     break;
   3845   case TALER_MERCHANT_CONTRACT_VERSION_1:
   3846     {
   3847       const struct TALER_MERCHANT_ContractChoice *selected
   3848         = &pc->check_contract.contract_terms->details.v1.choices[
   3849             pc->parse_wallet_data.choice_index];
   3850       unsigned int output_off;
   3851       unsigned int cnt;
   3852 
   3853       pc->validate_tokens.max_fee = selected->max_fee;
   3854       pc->validate_tokens.brutto = selected->amount;
   3855 
   3856       for (unsigned int i = 0; i<selected->inputs_len; i++)
   3857       {
   3858         const struct TALER_MERCHANT_ContractInput *input
   3859           = &selected->inputs[i];
   3860         const struct TALER_MERCHANT_ContractTokenFamily *family;
   3861 
   3862         switch (input->type)
   3863         {
   3864         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
   3865           GNUNET_break (0);
   3866           pay_end (pc,
   3867                    TALER_MHD_reply_with_error (
   3868                      pc->connection,
   3869                      MHD_HTTP_BAD_REQUEST,
   3870                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3871                      "input token type not valid"));
   3872           return;
   3873 #if FUTURE
   3874         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN:
   3875           GNUNET_break (0);
   3876           pay_end (pc,
   3877                    TALER_MHD_reply_with_error (
   3878                      pc->connection,
   3879                      MHD_HTTP_NOT_IMPLEMENTED,
   3880                      TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE,
   3881                      "token type not yet supported"));
   3882           return;
   3883 #endif
   3884         case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
   3885           family = find_family (pc,
   3886                                 input->details.token.token_family_slug);
   3887           if (NULL == family)
   3888           {
   3889             /* this should never happen, since the choices and
   3890                token families are validated on insert. */
   3891             GNUNET_break (0);
   3892             pay_end (pc,
   3893                      TALER_MHD_reply_with_error (
   3894                        pc->connection,
   3895                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3896                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
   3897                        "token family not found in order"));
   3898             return;
   3899           }
   3900           if (GNUNET_NO ==
   3901               find_valid_input_tokens (pc,
   3902                                        family,
   3903                                        i,
   3904                                        input->details.token.count))
   3905           {
   3906             /* Error is already scheduled from find_valid_input_token. */
   3907             return;
   3908           }
   3909         }
   3910       }
   3911 
   3912       /* calculate pc->output_tokens_len */
   3913       output_off = 0;
   3914       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3915       {
   3916         const struct TALER_MERCHANT_ContractOutput *output
   3917           = &selected->outputs[i];
   3918 
   3919         switch (output->type)
   3920         {
   3921         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   3922           GNUNET_assert (0);
   3923           break;
   3924         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   3925           cnt = output->details.token.count;
   3926           if (output_off + cnt < output_off)
   3927           {
   3928             GNUNET_break_op (0);
   3929             pay_end (pc,
   3930                      TALER_MHD_reply_with_error (
   3931                        pc->connection,
   3932                        MHD_HTTP_BAD_REQUEST,
   3933                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3934                        "output token counter overflow"));
   3935             return;
   3936           }
   3937           output_off += cnt;
   3938           break;
   3939         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   3940           /* check that this output type appears at most once */
   3941           if (pc->validate_tokens.donau_output_index >= 0)
   3942           {
   3943             /* This should have been prevented when the
   3944                contract was initially created */
   3945             GNUNET_break (0);
   3946             pay_end (pc,
   3947                      TALER_MHD_reply_with_error (
   3948                        pc->connection,
   3949                        MHD_HTTP_INTERNAL_SERVER_ERROR,
   3950                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
   3951                        "two donau output sets in same contract"));
   3952             return;
   3953           }
   3954           pc->validate_tokens.donau_output_index = i;
   3955 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   3956           if (output_off + pc->parse_wallet_data.num_bkps < output_off)
   3957           {
   3958             GNUNET_break_op (0);
   3959             pay_end (pc,
   3960                      TALER_MHD_reply_with_error (
   3961                        pc->connection,
   3962                        MHD_HTTP_BAD_REQUEST,
   3963                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
   3964                        "output token counter overflow"));
   3965             return;
   3966           }
   3967           output_off += pc->parse_wallet_data.num_bkps;
   3968 #endif
   3969           break;
   3970         }
   3971       }
   3972 
   3973 
   3974       pc->output_tokens_len = output_off;
   3975       pc->output_tokens
   3976         = GNUNET_new_array (pc->output_tokens_len,
   3977                             struct SignedOutputToken);
   3978 
   3979       /* calculate pc->output_tokens[].output_index */
   3980       output_off = 0;
   3981       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3982       {
   3983         const struct TALER_MERCHANT_ContractOutput *output
   3984           = &selected->outputs[i];
   3985         cnt = count_output_tokens (pc,
   3986                                    output);
   3987         for (unsigned int j = 0; j<cnt; j++)
   3988           pc->output_tokens[output_off + j].output_index = i;
   3989         output_off += cnt;
   3990       }
   3991 
   3992       /* compute non-donau outputs */
   3993       output_off = 0;
   3994       for (unsigned int i = 0; i<selected->outputs_len; i++)
   3995       {
   3996         const struct TALER_MERCHANT_ContractOutput *output
   3997           = &selected->outputs[i];
   3998 
   3999         switch (output->type)
   4000         {
   4001         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
   4002           GNUNET_assert (0);
   4003           break;
   4004         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
   4005           cnt = output->details.token.count;
   4006           GNUNET_assert (output_off + cnt
   4007                          <= pc->output_tokens_len);
   4008           if (GNUNET_OK !=
   4009               handle_output_token (pc,
   4010                                    output,
   4011                                    output_off))
   4012           {
   4013             /* Error is already scheduled from handle_output_token. */
   4014             return;
   4015           }
   4016           output_off += cnt;
   4017           break;
   4018         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
   4019 #ifndef HAVE_DONAU_DONAU_SERVICE_H
   4020           /* We checked at parse time, and
   4021              wallet didn't want donau, so OK! */
   4022           return;
   4023 #else
   4024           if ( (0 != pc->parse_wallet_data.num_bkps) &&
   4025                (GNUNET_OK !=
   4026                 handle_output_donation_receipt (pc,
   4027                                                 output)) )
   4028           {
   4029             /* Error is already scheduled from handle_output_donation_receipt. */
   4030             return;
   4031           }
   4032           output_off += pc->parse_wallet_data.num_bkps;
   4033           continue;
   4034 #endif
   4035         } /* switch on output token */
   4036       } /* for all output token types */
   4037     } /* case contract v1 */
   4038     break;
   4039   } /* switch on contract type */
   4040 
   4041   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4042   {
   4043     const struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   4044 
   4045     if (GNUNET_OK !=
   4046         TALER_amount_cmp_currency (&dc->cdd.amount,
   4047                                    &pc->validate_tokens.brutto))
   4048     {
   4049       GNUNET_break_op (0);
   4050       pay_end (pc,
   4051                TALER_MHD_reply_with_error (
   4052                  pc->connection,
   4053                  MHD_HTTP_CONFLICT,
   4054                  TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
   4055                  pc->validate_tokens.brutto.currency));
   4056       return;
   4057     }
   4058   }
   4059 
   4060   pc->phase = PP_COMPUTE_MONEY_POTS;
   4061 }
   4062 
   4063 
   4064 /**
   4065  * Function called with information about a coin that was deposited.
   4066  * Checks if this coin is in our list of deposits as well.
   4067  *
   4068  * @param cls closure with our `struct PayContext *`
   4069  * @param deposit_serial which deposit operation is this about
   4070  * @param exchange_url URL of the exchange that issued the coin
   4071  * @param h_wire hash of merchant's wire details
   4072  * @param deposit_timestamp when was the deposit made
   4073  * @param amount_with_fee amount the exchange will deposit for this coin
   4074  * @param deposit_fee fee the exchange will charge for this coin
   4075  * @param coin_pub public key of the coin
   4076  */
   4077 static void
   4078 deposit_paid_check (
   4079   void *cls,
   4080   uint64_t deposit_serial,
   4081   const char *exchange_url,
   4082   const struct TALER_MerchantWireHashP *h_wire,
   4083   struct GNUNET_TIME_Timestamp deposit_timestamp,
   4084   const struct TALER_Amount *amount_with_fee,
   4085   const struct TALER_Amount *deposit_fee,
   4086   const struct TALER_CoinSpendPublicKeyP *coin_pub)
   4087 {
   4088   struct PayContext *pc = cls;
   4089 
   4090   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4091   {
   4092     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4093 
   4094     if ( (0 ==
   4095           GNUNET_memcmp (&dci->cdd.coin_pub,
   4096                          coin_pub)) &&
   4097          (0 ==
   4098           strcmp (dci->exchange_url,
   4099                   exchange_url)) &&
   4100          (GNUNET_YES ==
   4101           TALER_amount_cmp_currency (&dci->cdd.amount,
   4102                                      amount_with_fee)) &&
   4103          (0 ==
   4104           TALER_amount_cmp (&dci->cdd.amount,
   4105                             amount_with_fee)) )
   4106     {
   4107       dci->matched_in_db = true;
   4108       break;
   4109     }
   4110   }
   4111 }
   4112 
   4113 
   4114 /**
   4115  * Function called with information about a token that was spent.
   4116  * FIXME: Replace this with a more specific function for this cb
   4117  *
   4118  * @param cls closure with `struct PayContext *`
   4119  * @param spent_token_serial "serial" of the spent token unused
   4120  * @param h_contract_terms hash of the contract terms unused
   4121  * @param h_issue_pub hash of the token issue public key unused
   4122  * @param use_pub public key of the token
   4123  * @param use_sig signature of the token
   4124  * @param issue_sig signature of the token issue
   4125  */
   4126 static void
   4127 input_tokens_paid_check (
   4128   void *cls,
   4129   uint64_t spent_token_serial,
   4130   const struct TALER_PrivateContractHashP *h_contract_terms,
   4131   const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub,
   4132   const struct TALER_TokenUsePublicKeyP *use_pub,
   4133   const struct TALER_TokenUseSignatureP *use_sig,
   4134   const struct TALER_TokenIssueSignature *issue_sig)
   4135 {
   4136   struct PayContext *pc = cls;
   4137 
   4138   for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++)
   4139   {
   4140     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   4141 
   4142     if ( (0 ==
   4143           GNUNET_memcmp (&tuc->pub,
   4144                          use_pub)) &&
   4145          (0 ==
   4146           GNUNET_memcmp (&tuc->sig,
   4147                          use_sig)) &&
   4148          (0 ==
   4149           GNUNET_memcmp (&tuc->unblinded_sig,
   4150                          issue_sig)) )
   4151     {
   4152       tuc->found_in_db = true;
   4153       break;
   4154     }
   4155   }
   4156 }
   4157 
   4158 
   4159 /**
   4160  * Small helper function to append an output token signature from db
   4161  *
   4162  * @param cls closure with `struct PayContext *`
   4163  * @param h_issue hash of the token
   4164  * @param sig signature of the token
   4165  */
   4166 static void
   4167 append_output_token_sig (void *cls,
   4168                          struct GNUNET_HashCode *h_issue,
   4169                          struct GNUNET_CRYPTO_BlindedSignature *sig)
   4170 {
   4171   struct PayContext *pc = cls;
   4172   struct TALER_MERCHANT_ContractChoice *choice;
   4173   const struct TALER_MERCHANT_ContractOutput *output;
   4174   struct SignedOutputToken out;
   4175   unsigned int cnt;
   4176 
   4177   GNUNET_assert (TALER_MERCHANT_CONTRACT_VERSION_1 ==
   4178                  pc->check_contract.contract_terms->version);
   4179   choice = &pc->check_contract.contract_terms->details.v1
   4180            .choices[pc->parse_wallet_data.choice_index];
   4181   output = &choice->outputs[pc->output_index_gen];
   4182   cnt = count_output_tokens (pc,
   4183                              output);
   4184   out.output_index = pc->output_index_gen;
   4185   out.h_issue.hash = *h_issue;
   4186   out.sig.signature = sig;
   4187   GNUNET_CRYPTO_blind_sig_incref (sig);
   4188   GNUNET_array_append (pc->output_tokens,
   4189                        pc->output_tokens_len,
   4190                        out);
   4191   /* Go to next output once we've output all tokens for the current one. */
   4192   pc->output_token_cnt++;
   4193   if (pc->output_token_cnt >= cnt)
   4194   {
   4195     pc->output_token_cnt = 0;
   4196     pc->output_index_gen++;
   4197   }
   4198 }
   4199 
   4200 
   4201 /**
   4202  * Handle case where contract was already paid. Either decides
   4203  * the payment is idempotent, or refunds the excess payment.
   4204  *
   4205  * @param[in,out] pc context we use to handle the payment
   4206  */
   4207 static void
   4208 phase_contract_paid (struct PayContext *pc)
   4209 {
   4210   json_t *refunds;
   4211   bool unmatched = false;
   4212 
   4213   {
   4214     enum GNUNET_DB_QueryStatus qs;
   4215 
   4216     qs = TMH_db->lookup_deposits_by_order (TMH_db->cls,
   4217                                            pc->check_contract.order_serial,
   4218                                            &deposit_paid_check,
   4219                                            pc);
   4220     /* Since orders with choices can have a price of zero,
   4221        0 is also a valid query state */
   4222     if (qs < 0)
   4223     {
   4224       GNUNET_break (0);
   4225       pay_end (pc,
   4226                TALER_MHD_reply_with_error (
   4227                  pc->connection,
   4228                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4229                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4230                  "lookup_deposits_by_order"));
   4231       return;
   4232     }
   4233   }
   4234   for (size_t i = 0;
   4235        i<pc->parse_pay.coins_cnt && ! unmatched;
   4236        i++)
   4237   {
   4238     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4239 
   4240     if (! dci->matched_in_db)
   4241       unmatched = true;
   4242   }
   4243   /* Check if provided input tokens match token in the database */
   4244   {
   4245     enum GNUNET_DB_QueryStatus qs;
   4246 
   4247     /* FIXME-Optimization: Maybe use h_contract instead of order_serial here? */
   4248     qs = TMH_db->lookup_spent_tokens_by_order (TMH_db->cls,
   4249                                                pc->check_contract.order_serial,
   4250                                                &input_tokens_paid_check,
   4251                                                pc);
   4252 
   4253     if (qs < 0)
   4254     {
   4255       GNUNET_break (0);
   4256       pay_end (pc,
   4257                TALER_MHD_reply_with_error (
   4258                  pc->connection,
   4259                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4260                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4261                  "lookup_spent_tokens_by_order"));
   4262       return;
   4263     }
   4264   }
   4265   for (size_t i = 0; i<pc->parse_pay.tokens_cnt && ! unmatched; i++)
   4266   {
   4267     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   4268 
   4269     if (! tuc->found_in_db)
   4270       unmatched = true;
   4271   }
   4272 
   4273   /* In this part we are fetching token_sigs related output */
   4274   if (! unmatched)
   4275   {
   4276     /* Everything fine, idempotent request, generate response immediately */
   4277     enum GNUNET_DB_QueryStatus qs;
   4278 
   4279     pc->output_index_gen = 0;
   4280     qs = TMH_db->select_order_blinded_sigs (
   4281       TMH_db->cls,
   4282       pc->order_id,
   4283       &append_output_token_sig,
   4284       pc);
   4285     if (0 > qs)
   4286     {
   4287       GNUNET_break (0);
   4288       pay_end (pc,
   4289                TALER_MHD_reply_with_error (
   4290                  pc->connection,
   4291                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4292                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4293                  "select_order_blinded_sigs"));
   4294       return;
   4295     }
   4296 
   4297     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4298                 "Idempotent pay request for order `%s', signing again\n",
   4299                 pc->order_id);
   4300     pc->phase = PP_SUCCESS_RESPONSE;
   4301     return;
   4302   }
   4303   /* Conflict, double-payment detected! */
   4304   /* FIXME-#8674: What should we do with input tokens?
   4305      Currently there is no refund for tokens. */
   4306   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4307               "Client attempted to pay extra for already paid order `%s'\n",
   4308               pc->order_id);
   4309   refunds = json_array ();
   4310   GNUNET_assert (NULL != refunds);
   4311   for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++)
   4312   {
   4313     struct DepositConfirmation *dci = &pc->parse_pay.dc[i];
   4314     struct TALER_MerchantSignatureP merchant_sig;
   4315 
   4316     if (dci->matched_in_db)
   4317       continue;
   4318     TALER_merchant_refund_sign (&dci->cdd.coin_pub,
   4319                                 &pc->check_contract.h_contract_terms,
   4320                                 0, /* rtransaction id */
   4321                                 &dci->cdd.amount,
   4322                                 &pc->hc->instance->merchant_priv,
   4323                                 &merchant_sig);
   4324     GNUNET_assert (
   4325       0 ==
   4326       json_array_append_new (
   4327         refunds,
   4328         GNUNET_JSON_PACK (
   4329           GNUNET_JSON_pack_data_auto (
   4330             "coin_pub",
   4331             &dci->cdd.coin_pub),
   4332           GNUNET_JSON_pack_data_auto (
   4333             "merchant_sig",
   4334             &merchant_sig),
   4335           TALER_JSON_pack_amount ("amount",
   4336                                   &dci->cdd.amount),
   4337           GNUNET_JSON_pack_uint64 ("rtransaction_id",
   4338                                    0))));
   4339   }
   4340   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4341               "Generating JSON response with code %d\n",
   4342               (int) TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID);
   4343   pay_end (pc,
   4344            TALER_MHD_REPLY_JSON_PACK (
   4345              pc->connection,
   4346              MHD_HTTP_CONFLICT,
   4347              TALER_MHD_PACK_EC (
   4348                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID),
   4349              GNUNET_JSON_pack_array_steal ("refunds",
   4350                                            refunds)));
   4351 }
   4352 
   4353 
   4354 /**
   4355  * Check the database state for the given order.
   4356  * Schedules an error response in the connection on failure.
   4357  *
   4358  * @param[in,out] pc context we use to handle the payment
   4359  */
   4360 static void
   4361 phase_check_contract (struct PayContext *pc)
   4362 {
   4363   /* obtain contract terms */
   4364   enum GNUNET_DB_QueryStatus qs;
   4365   bool paid = false;
   4366 
   4367   if (NULL != pc->check_contract.contract_terms_json)
   4368   {
   4369     json_decref (pc->check_contract.contract_terms_json);
   4370     pc->check_contract.contract_terms_json = NULL;
   4371   }
   4372   if (NULL != pc->check_contract.contract_terms)
   4373   {
   4374     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   4375     pc->check_contract.contract_terms = NULL;
   4376   }
   4377   qs = TMH_db->lookup_contract_terms2 (TMH_db->cls,
   4378                                        pc->hc->instance->settings.id,
   4379                                        pc->order_id,
   4380                                        &pc->check_contract.contract_terms_json,
   4381                                        &pc->check_contract.order_serial,
   4382                                        &paid,
   4383                                        NULL,
   4384                                        &pc->check_contract.pos_key,
   4385                                        &pc->check_contract.pos_alg);
   4386   if (0 > qs)
   4387   {
   4388     /* single, read-only SQL statements should never cause
   4389        serialization problems */
   4390     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
   4391     /* Always report on hard error to enable diagnostics */
   4392     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
   4393     pay_end (pc,
   4394              TALER_MHD_reply_with_error (
   4395                pc->connection,
   4396                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4397                TALER_EC_GENERIC_DB_FETCH_FAILED,
   4398                "contract terms"));
   4399     return;
   4400   }
   4401   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   4402   {
   4403     pay_end (pc,
   4404              TALER_MHD_reply_with_error (
   4405                pc->connection,
   4406                MHD_HTTP_NOT_FOUND,
   4407                TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
   4408                pc->order_id));
   4409     return;
   4410   }
   4411   /* hash contract (needed later) */
   4412 #if DEBUG
   4413   json_dumpf (pc->check_contract.contract_terms_json,
   4414               stderr,
   4415               JSON_INDENT (2));
   4416 #endif
   4417   if (GNUNET_OK !=
   4418       TALER_JSON_contract_hash (pc->check_contract.contract_terms_json,
   4419                                 &pc->check_contract.h_contract_terms))
   4420   {
   4421     GNUNET_break (0);
   4422     pay_end (pc,
   4423              TALER_MHD_reply_with_error (
   4424                pc->connection,
   4425                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4426                TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH,
   4427                NULL));
   4428     return;
   4429   }
   4430 
   4431   /* Parse the contract terms even for paid orders,
   4432      as later phases need it. */
   4433 
   4434   pc->check_contract.contract_terms = TALER_MERCHANT_contract_parse (
   4435     pc->check_contract.contract_terms_json,
   4436     true);
   4437 
   4438   if (NULL == pc->check_contract.contract_terms)
   4439   {
   4440     /* invalid contract */
   4441     GNUNET_break (0);
   4442     pay_end (pc,
   4443              TALER_MHD_reply_with_error (
   4444                pc->connection,
   4445                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4446                TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
   4447                pc->order_id));
   4448     return;
   4449   }
   4450 
   4451   if (paid)
   4452   {
   4453     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4454                 "Order `%s' paid, checking for double-payment\n",
   4455                 pc->order_id);
   4456     pc->phase = PP_CONTRACT_PAID;
   4457     return;
   4458   }
   4459   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4460               "Handling payment for order `%s' with contract hash `%s'\n",
   4461               pc->order_id,
   4462               GNUNET_h2s (&pc->check_contract.h_contract_terms.hash));
   4463 
   4464   /* Check fundamentals */
   4465   {
   4466     switch (pc->check_contract.contract_terms->version)
   4467     {
   4468     case TALER_MERCHANT_CONTRACT_VERSION_0:
   4469       {
   4470         if (pc->parse_wallet_data.choice_index > 0)
   4471         {
   4472           GNUNET_break (0);
   4473           pay_end (pc,
   4474                    TALER_MHD_reply_with_error (
   4475                      pc->connection,
   4476                      MHD_HTTP_BAD_REQUEST,
   4477                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4478                      "contract terms v0 has no choices"));
   4479           return;
   4480         }
   4481       }
   4482       break;
   4483     case TALER_MERCHANT_CONTRACT_VERSION_1:
   4484       {
   4485         if (pc->parse_wallet_data.choice_index < 0)
   4486         {
   4487           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4488                       "Order `%s' has non-empty choices array but"
   4489                       "request is missing 'choice_index' field\n",
   4490                       pc->order_id);
   4491           GNUNET_break (0);
   4492           pay_end (pc,
   4493                    TALER_MHD_reply_with_error (
   4494                      pc->connection,
   4495                      MHD_HTTP_BAD_REQUEST,
   4496                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING,
   4497                      NULL));
   4498           return;
   4499         }
   4500         if (pc->parse_wallet_data.choice_index >=
   4501             pc->check_contract.contract_terms->details.v1.choices_len)
   4502         {
   4503           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4504                       "Order `%s' has choices array with %u elements but "
   4505                       "request has 'choice_index' field with value %d\n",
   4506                       pc->order_id,
   4507                       pc->check_contract.contract_terms->details.v1.choices_len,
   4508                       pc->parse_wallet_data.choice_index);
   4509           GNUNET_break (0);
   4510           pay_end (pc,
   4511                    TALER_MHD_reply_with_error (
   4512                      pc->connection,
   4513                      MHD_HTTP_BAD_REQUEST,
   4514                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS,
   4515                      NULL));
   4516           return;
   4517         }
   4518       }
   4519       break;
   4520     default:
   4521       GNUNET_break (0);
   4522       pay_end (pc,
   4523                TALER_MHD_reply_with_error (
   4524                  pc->connection,
   4525                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4526                  TALER_EC_GENERIC_DB_FETCH_FAILED,
   4527                  "contract 'version' in database not supported by this backend")
   4528                );
   4529       return;
   4530     }
   4531   }
   4532 
   4533   if (GNUNET_TIME_timestamp_cmp (pc->check_contract.contract_terms->
   4534                                  wire_deadline,
   4535                                  <,
   4536                                  pc->check_contract.contract_terms->
   4537                                  refund_deadline))
   4538   {
   4539     /* This should already have been checked when creating the order! */
   4540     GNUNET_break (0);
   4541     pay_end (pc,
   4542              TALER_MHD_reply_with_error (
   4543                pc->connection,
   4544                MHD_HTTP_INTERNAL_SERVER_ERROR,
   4545                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
   4546                NULL));
   4547     return;
   4548   }
   4549   if (GNUNET_TIME_absolute_is_past (pc->check_contract.contract_terms->
   4550                                     pay_deadline.abs_time))
   4551   {
   4552     /* too late */
   4553     pay_end (pc,
   4554              TALER_MHD_reply_with_error (
   4555                pc->connection,
   4556                MHD_HTTP_GONE,
   4557                TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED,
   4558                NULL));
   4559     return;
   4560   }
   4561 
   4562 /* Make sure wire method (still) exists for this instance */
   4563   {
   4564     struct TMH_WireMethod *wm;
   4565 
   4566     wm = pc->hc->instance->wm_head;
   4567     while (0 != GNUNET_memcmp (&pc->check_contract.contract_terms->h_wire,
   4568                                &wm->h_wire))
   4569       wm = wm->next;
   4570     if (NULL == wm)
   4571     {
   4572       GNUNET_break (0);
   4573       pay_end (pc,
   4574                TALER_MHD_reply_with_error (
   4575                  pc->connection,
   4576                  MHD_HTTP_INTERNAL_SERVER_ERROR,
   4577                  TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN,
   4578                  NULL));
   4579       return;
   4580     }
   4581     pc->check_contract.wm = wm;
   4582   }
   4583   pc->phase = PP_VALIDATE_TOKENS;
   4584 }
   4585 
   4586 
   4587 /**
   4588  * Try to parse the wallet_data object of the pay request into
   4589  * the given context. Schedules an error response in the connection
   4590  * on failure.
   4591  *
   4592  * @param[in,out] pc context we use to handle the payment
   4593  */
   4594 static void
   4595 phase_parse_wallet_data (struct PayContext *pc)
   4596 {
   4597   const json_t *tokens_evs;
   4598   const json_t *donau_obj;
   4599 
   4600   struct GNUNET_JSON_Specification spec[] = {
   4601     GNUNET_JSON_spec_mark_optional (
   4602       GNUNET_JSON_spec_int16 ("choice_index",
   4603                               &pc->parse_wallet_data.choice_index),
   4604       NULL),
   4605     GNUNET_JSON_spec_mark_optional (
   4606       GNUNET_JSON_spec_array_const ("tokens_evs",
   4607                                     &tokens_evs),
   4608       NULL),
   4609     GNUNET_JSON_spec_mark_optional (
   4610       GNUNET_JSON_spec_object_const ("donau",
   4611                                      &donau_obj),
   4612       NULL),
   4613     GNUNET_JSON_spec_end ()
   4614   };
   4615 
   4616   pc->parse_wallet_data.choice_index = -1;
   4617   if (NULL == pc->parse_pay.wallet_data)
   4618   {
   4619     pc->phase = PP_CHECK_CONTRACT;
   4620     return;
   4621   }
   4622   {
   4623     enum GNUNET_GenericReturnValue res;
   4624 
   4625     res = TALER_MHD_parse_json_data (pc->connection,
   4626                                      pc->parse_pay.wallet_data,
   4627                                      spec);
   4628     if (GNUNET_YES != res)
   4629     {
   4630       GNUNET_break_op (0);
   4631       pay_end (pc,
   4632                (GNUNET_NO == res)
   4633              ? MHD_YES
   4634              : MHD_NO);
   4635       return;
   4636     }
   4637   }
   4638 
   4639   pc->parse_wallet_data.token_envelopes_cnt
   4640     = json_array_size (tokens_evs);
   4641   if (pc->parse_wallet_data.token_envelopes_cnt >
   4642       MAX_TOKEN_ALLOWED_OUTPUTS)
   4643   {
   4644     GNUNET_break_op (0);
   4645     pay_end (pc,
   4646              TALER_MHD_reply_with_error (
   4647                pc->connection,
   4648                MHD_HTTP_BAD_REQUEST,
   4649                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4650                "'tokens_evs' array too long"));
   4651     return;
   4652   }
   4653   pc->parse_wallet_data.token_envelopes
   4654     = GNUNET_new_array (pc->parse_wallet_data.token_envelopes_cnt,
   4655                         struct TokenEnvelope);
   4656 
   4657   {
   4658     unsigned int tokens_ev_index;
   4659     json_t *token_ev;
   4660 
   4661     json_array_foreach (tokens_evs,
   4662                         tokens_ev_index,
   4663                         token_ev)
   4664     {
   4665       struct TokenEnvelope *ev
   4666         = &pc->parse_wallet_data.token_envelopes[tokens_ev_index];
   4667       struct GNUNET_JSON_Specification ispec[] = {
   4668         TALER_JSON_spec_token_envelope (NULL,
   4669                                         &ev->blinded_token),
   4670         GNUNET_JSON_spec_end ()
   4671       };
   4672       enum GNUNET_GenericReturnValue res;
   4673 
   4674       if (json_is_null (token_ev))
   4675         continue;
   4676       res = TALER_MHD_parse_json_data (pc->connection,
   4677                                        token_ev,
   4678                                        ispec);
   4679       if (GNUNET_YES != res)
   4680       {
   4681         GNUNET_break_op (0);
   4682         pay_end (pc,
   4683                  (GNUNET_NO == res)
   4684                  ? MHD_YES
   4685                  : MHD_NO);
   4686         return;
   4687       }
   4688 
   4689       for (unsigned int j = 0; j<tokens_ev_index; j++)
   4690       {
   4691         if (0 ==
   4692             GNUNET_memcmp (ev->blinded_token.blinded_pub,
   4693                            pc->parse_wallet_data.token_envelopes[j].
   4694                            blinded_token.blinded_pub))
   4695         {
   4696           GNUNET_break_op (0);
   4697           pay_end (pc,
   4698                    TALER_MHD_reply_with_error (
   4699                      pc->connection,
   4700                      MHD_HTTP_BAD_REQUEST,
   4701                      TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4702                      "duplicate token envelope in list"));
   4703           return;
   4704         }
   4705       }
   4706     }
   4707   }
   4708 
   4709 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   4710   if (NULL != donau_obj)
   4711   {
   4712     const char *donau_url_tmp;
   4713     const json_t *budikeypairs;
   4714     json_t *donau_keys_json;
   4715 
   4716     /* Fetching and checking that all 3 are present in some way */
   4717     struct GNUNET_JSON_Specification dspec[] = {
   4718       GNUNET_JSON_spec_string      ("url",
   4719                                     &donau_url_tmp),
   4720       GNUNET_JSON_spec_uint64      ("year",
   4721                                     &pc->parse_wallet_data.donau.donation_year),
   4722       GNUNET_JSON_spec_array_const ("budikeypairs",
   4723                                     &budikeypairs),
   4724       GNUNET_JSON_spec_end ()
   4725     };
   4726     enum GNUNET_GenericReturnValue res;
   4727 
   4728     res = TALER_MHD_parse_json_data (pc->connection,
   4729                                      donau_obj,
   4730                                      dspec);
   4731     if (GNUNET_YES != res)
   4732     {
   4733       GNUNET_break_op (0);
   4734       pay_end (pc,
   4735                (GNUNET_NO == res)
   4736                ? MHD_YES
   4737                : MHD_NO);
   4738       return;
   4739     }
   4740 
   4741     /* Check if the needed data is present for the given donau URL */
   4742     {
   4743       enum GNUNET_DB_QueryStatus qs;
   4744 
   4745       qs = TMH_db->lookup_order_charity (
   4746         TMH_db->cls,
   4747         pc->hc->instance->settings.id,
   4748         donau_url_tmp,
   4749         &pc->parse_wallet_data.charity_id,
   4750         &pc->parse_wallet_data.charity_priv,
   4751         &pc->parse_wallet_data.charity_max_per_year,
   4752         &pc->parse_wallet_data.charity_receipts_to_date,
   4753         &donau_keys_json,
   4754         &pc->parse_wallet_data.donau_instance_serial);
   4755 
   4756       switch (qs)
   4757       {
   4758       case GNUNET_DB_STATUS_HARD_ERROR:
   4759       case GNUNET_DB_STATUS_SOFT_ERROR:
   4760         TMH_db->rollback (TMH_db->cls);
   4761         pay_end (pc,
   4762                  TALER_MHD_reply_with_error (
   4763                    pc->connection,
   4764                    MHD_HTTP_INTERNAL_SERVER_ERROR,
   4765                    TALER_EC_GENERIC_DB_FETCH_FAILED,
   4766                    "lookup_order_charity"));
   4767         return;
   4768       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   4769         TMH_db->rollback (TMH_db->cls);
   4770         pay_end (pc,
   4771                  TALER_MHD_reply_with_error (
   4772                    pc->connection,
   4773                    MHD_HTTP_NOT_FOUND,
   4774                    TALER_EC_MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN,
   4775                    donau_url_tmp));
   4776         return;
   4777       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   4778         pc->parse_wallet_data.donau.donau_url =
   4779           GNUNET_strdup (donau_url_tmp);
   4780         break;
   4781       }
   4782     }
   4783 
   4784     {
   4785       pc->parse_wallet_data.donau_keys =
   4786         DONAU_keys_from_json (donau_keys_json);
   4787       json_decref (donau_keys_json);
   4788       if (NULL == pc->parse_wallet_data.donau_keys)
   4789       {
   4790         GNUNET_break_op (0);
   4791         pay_end (pc,
   4792                  TALER_MHD_reply_with_error (pc->connection,
   4793                                              MHD_HTTP_BAD_REQUEST,
   4794                                              TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4795                                              "Invalid donau_keys"));
   4796         return;
   4797       }
   4798     }
   4799 
   4800     /* Stage to parse the budikeypairs from json to struct */
   4801     if (0 != json_array_size (budikeypairs))
   4802     {
   4803       size_t num_bkps = json_array_size (budikeypairs);
   4804       struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps =
   4805         GNUNET_new_array (num_bkps,
   4806                           struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
   4807 
   4808       /* Change to json for each*/
   4809       for (size_t i = 0; i < num_bkps; i++)
   4810       {
   4811         const json_t *bkp_obj = json_array_get (budikeypairs,
   4812                                                 i);
   4813         if (GNUNET_SYSERR ==
   4814             merchant_parse_json_bkp (&bkps[i],
   4815                                      bkp_obj))
   4816         {
   4817           GNUNET_break_op (0);
   4818           for (size_t j = 0; i < j; j++)
   4819             GNUNET_CRYPTO_blinded_message_decref (
   4820               bkps[j].blinded_udi.blinded_message);
   4821           GNUNET_free (bkps);
   4822           pay_end (pc,
   4823                    TALER_MHD_reply_with_error (pc->connection,
   4824                                                MHD_HTTP_BAD_REQUEST,
   4825                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4826                                                "Failed to parse budikeypairs"));
   4827           return;
   4828         }
   4829       }
   4830 
   4831       pc->parse_wallet_data.num_bkps = num_bkps;
   4832       pc->parse_wallet_data.bkps = bkps;
   4833     }
   4834   }
   4835 #else
   4836   /* Donau not compiled in: reject request if a donau object was given. */
   4837   if (NULL != donau_obj)
   4838   {
   4839     pay_end (pc,
   4840              TALER_MHD_reply_with_error (
   4841                pc->connection,
   4842                MHD_HTTP_NOT_IMPLEMENTED,
   4843                TALER_EC_MERCHANT_GENERIC_DONAU_NOT_CONFIGURED,
   4844                "donau support disabled"));
   4845     return;
   4846   }
   4847 #endif /* HAVE_DONAU_DONAU_SERVICE_H */
   4848 
   4849   TALER_json_hash (pc->parse_pay.wallet_data,
   4850                    &pc->parse_wallet_data.h_wallet_data);
   4851 
   4852   pc->phase = PP_CHECK_CONTRACT;
   4853 }
   4854 
   4855 
   4856 /**
   4857  * Try to parse the pay request into the given pay context.
   4858  * Schedules an error response in the connection on failure.
   4859  *
   4860  * @param[in,out] pc context we use to handle the payment
   4861  */
   4862 static void
   4863 phase_parse_pay (struct PayContext *pc)
   4864 {
   4865   const char *session_id = NULL;
   4866   const json_t *coins;
   4867   const json_t *tokens;
   4868   struct GNUNET_JSON_Specification spec[] = {
   4869     GNUNET_JSON_spec_array_const ("coins",
   4870                                   &coins),
   4871     GNUNET_JSON_spec_mark_optional (
   4872       GNUNET_JSON_spec_string ("session_id",
   4873                                &session_id),
   4874       NULL),
   4875     GNUNET_JSON_spec_mark_optional (
   4876       GNUNET_JSON_spec_object_const ("wallet_data",
   4877                                      &pc->parse_pay.wallet_data),
   4878       NULL),
   4879     GNUNET_JSON_spec_mark_optional (
   4880       GNUNET_JSON_spec_array_const ("tokens",
   4881                                     &tokens),
   4882       NULL),
   4883     GNUNET_JSON_spec_end ()
   4884   };
   4885 
   4886 #if DEBUG
   4887   {
   4888     char *dump = json_dumps (pc->hc->request_body,
   4889                              JSON_INDENT (2)
   4890                              | JSON_ENCODE_ANY
   4891                              | JSON_SORT_KEYS);
   4892 
   4893     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4894                 "POST /orders/%s/pay – request body follows:\n%s\n",
   4895                 pc->order_id,
   4896                 dump);
   4897 
   4898     free (dump);
   4899 
   4900   }
   4901 #endif /* DEBUG */
   4902 
   4903   GNUNET_assert (PP_PARSE_PAY == pc->phase);
   4904   {
   4905     enum GNUNET_GenericReturnValue res;
   4906 
   4907     res = TALER_MHD_parse_json_data (pc->connection,
   4908                                      pc->hc->request_body,
   4909                                      spec);
   4910     if (GNUNET_YES != res)
   4911     {
   4912       GNUNET_break_op (0);
   4913       pay_end (pc,
   4914                (GNUNET_NO == res)
   4915                ? MHD_YES
   4916                : MHD_NO);
   4917       return;
   4918     }
   4919   }
   4920 
   4921   /* copy session ID (if set) */
   4922   if (NULL != session_id)
   4923   {
   4924     pc->parse_pay.session_id = GNUNET_strdup (session_id);
   4925   }
   4926   else
   4927   {
   4928     /* use empty string as default if client didn't specify it */
   4929     pc->parse_pay.session_id = GNUNET_strdup ("");
   4930   }
   4931 
   4932   pc->parse_pay.coins_cnt = json_array_size (coins);
   4933   if (pc->parse_pay.coins_cnt > MAX_COIN_ALLOWED_COINS)
   4934   {
   4935     GNUNET_break_op (0);
   4936     pay_end (pc,
   4937              TALER_MHD_reply_with_error (
   4938                pc->connection,
   4939                MHD_HTTP_BAD_REQUEST,
   4940                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   4941                "'coins' array too long"));
   4942     return;
   4943   }
   4944   /* note: 1 coin = 1 deposit confirmation expected */
   4945   pc->parse_pay.dc = GNUNET_new_array (pc->parse_pay.coins_cnt,
   4946                                        struct DepositConfirmation);
   4947 
   4948   /* This loop populates the array 'dc' in 'pc' */
   4949   {
   4950     unsigned int coins_index;
   4951     json_t *coin;
   4952 
   4953     json_array_foreach (coins, coins_index, coin)
   4954     {
   4955       struct DepositConfirmation *dc = &pc->parse_pay.dc[coins_index];
   4956       const char *exchange_url;
   4957       struct GNUNET_JSON_Specification ispec[] = {
   4958         GNUNET_JSON_spec_fixed_auto ("coin_sig",
   4959                                      &dc->cdd.coin_sig),
   4960         GNUNET_JSON_spec_fixed_auto ("coin_pub",
   4961                                      &dc->cdd.coin_pub),
   4962         TALER_JSON_spec_denom_sig ("ub_sig",
   4963                                    &dc->cdd.denom_sig),
   4964         GNUNET_JSON_spec_fixed_auto ("h_denom",
   4965                                      &dc->cdd.h_denom_pub),
   4966         TALER_JSON_spec_amount_any ("contribution",
   4967                                     &dc->cdd.amount),
   4968         TALER_JSON_spec_web_url ("exchange_url",
   4969                                  &exchange_url),
   4970         /* if a minimum age was required, the minimum_age_sig and
   4971          * age_commitment must be provided */
   4972         GNUNET_JSON_spec_mark_optional (
   4973           GNUNET_JSON_spec_fixed_auto ("minimum_age_sig",
   4974                                        &dc->minimum_age_sig),
   4975           &dc->no_minimum_age_sig),
   4976         GNUNET_JSON_spec_mark_optional (
   4977           TALER_JSON_spec_age_commitment ("age_commitment",
   4978                                           &dc->age_commitment),
   4979           &dc->no_age_commitment),
   4980         /* if minimum age was not required, but coin with age restriction set
   4981          * was used, h_age_commitment must be provided. */
   4982         GNUNET_JSON_spec_mark_optional (
   4983           GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
   4984                                        &dc->cdd.h_age_commitment),
   4985           &dc->no_h_age_commitment),
   4986         GNUNET_JSON_spec_end ()
   4987       };
   4988       enum GNUNET_GenericReturnValue res;
   4989       struct ExchangeGroup *eg = NULL;
   4990 
   4991       res = TALER_MHD_parse_json_data (pc->connection,
   4992                                        coin,
   4993                                        ispec);
   4994       if (GNUNET_YES != res)
   4995       {
   4996         GNUNET_break_op (0);
   4997         pay_end (pc,
   4998                  (GNUNET_NO == res)
   4999                  ? MHD_YES
   5000                  : MHD_NO);
   5001         return;
   5002       }
   5003       for (unsigned int j = 0; j<coins_index; j++)
   5004       {
   5005         if (0 ==
   5006             GNUNET_memcmp (&dc->cdd.coin_pub,
   5007                            &pc->parse_pay.dc[j].cdd.coin_pub))
   5008         {
   5009           GNUNET_break_op (0);
   5010           pay_end (pc,
   5011                    TALER_MHD_reply_with_error (pc->connection,
   5012                                                MHD_HTTP_BAD_REQUEST,
   5013                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5014                                                "duplicate coin in list"));
   5015           return;
   5016         }
   5017       }
   5018 
   5019       dc->exchange_url = GNUNET_strdup (exchange_url);
   5020       dc->index = coins_index;
   5021       dc->pc = pc;
   5022 
   5023       /* Check the consistency of the (potential) age restriction
   5024        * information. */
   5025       if (dc->no_age_commitment != dc->no_minimum_age_sig)
   5026       {
   5027         GNUNET_break_op (0);
   5028         pay_end (pc,
   5029                  TALER_MHD_reply_with_error (
   5030                    pc->connection,
   5031                    MHD_HTTP_BAD_REQUEST,
   5032                    TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5033                    "inconsistent: 'age_commitment' vs. 'minimum_age_sig'"
   5034                    ));
   5035         return;
   5036       }
   5037 
   5038       /* Setup exchange group */
   5039       for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   5040       {
   5041         if (0 ==
   5042             strcmp (pc->parse_pay.egs[i]->exchange_url,
   5043                     exchange_url))
   5044         {
   5045           eg = pc->parse_pay.egs[i];
   5046           break;
   5047         }
   5048       }
   5049       if (NULL == eg)
   5050       {
   5051         eg = GNUNET_new (struct ExchangeGroup);
   5052         eg->pc = pc;
   5053         eg->exchange_url = dc->exchange_url;
   5054         eg->total = dc->cdd.amount;
   5055         GNUNET_array_append (pc->parse_pay.egs,
   5056                              pc->parse_pay.num_exchanges,
   5057                              eg);
   5058       }
   5059       else
   5060       {
   5061         if (0 >
   5062             TALER_amount_add (&eg->total,
   5063                               &eg->total,
   5064                               &dc->cdd.amount))
   5065         {
   5066           GNUNET_break_op (0);
   5067           pay_end (pc,
   5068                    TALER_MHD_reply_with_error (
   5069                      pc->connection,
   5070                      MHD_HTTP_INTERNAL_SERVER_ERROR,
   5071                      TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW,
   5072                      "Overflow adding up amounts"));
   5073           return;
   5074         }
   5075       }
   5076     }
   5077   }
   5078 
   5079   pc->parse_pay.tokens_cnt = json_array_size (tokens);
   5080   if (pc->parse_pay.tokens_cnt > MAX_TOKEN_ALLOWED_INPUTS)
   5081   {
   5082     GNUNET_break_op (0);
   5083     pay_end (pc,
   5084              TALER_MHD_reply_with_error (
   5085                pc->connection,
   5086                MHD_HTTP_BAD_REQUEST,
   5087                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5088                "'tokens' array too long"));
   5089     return;
   5090   }
   5091 
   5092   pc->parse_pay.tokens = GNUNET_new_array (pc->parse_pay.tokens_cnt,
   5093                                            struct TokenUseConfirmation);
   5094 
   5095   /* This loop populates the array 'tokens' in 'pc' */
   5096   {
   5097     unsigned int tokens_index;
   5098     json_t *token;
   5099 
   5100     json_array_foreach (tokens, tokens_index, token)
   5101     {
   5102       struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[tokens_index];
   5103       struct GNUNET_JSON_Specification ispec[] = {
   5104         GNUNET_JSON_spec_fixed_auto ("token_sig",
   5105                                      &tuc->sig),
   5106         GNUNET_JSON_spec_fixed_auto ("token_pub",
   5107                                      &tuc->pub),
   5108         GNUNET_JSON_spec_fixed_auto ("h_issue",
   5109                                      &tuc->h_issue),
   5110         TALER_JSON_spec_token_issue_sig ("ub_sig",
   5111                                          &tuc->unblinded_sig),
   5112         GNUNET_JSON_spec_end ()
   5113       };
   5114       enum GNUNET_GenericReturnValue res;
   5115 
   5116       res = TALER_MHD_parse_json_data (pc->connection,
   5117                                        token,
   5118                                        ispec);
   5119       if (GNUNET_YES != res)
   5120       {
   5121         GNUNET_break_op (0);
   5122         pay_end (pc,
   5123                  (GNUNET_NO == res)
   5124                  ? MHD_YES
   5125                  : MHD_NO);
   5126         return;
   5127       }
   5128 
   5129       for (unsigned int j = 0; j<tokens_index; j++)
   5130       {
   5131         if (0 ==
   5132             GNUNET_memcmp (&tuc->pub,
   5133                            &pc->parse_pay.tokens[j].pub))
   5134         {
   5135           GNUNET_break_op (0);
   5136           pay_end (pc,
   5137                    TALER_MHD_reply_with_error (pc->connection,
   5138                                                MHD_HTTP_BAD_REQUEST,
   5139                                                TALER_EC_GENERIC_PARAMETER_MALFORMED,
   5140                                                "duplicate token in list"));
   5141           return;
   5142         }
   5143       }
   5144     }
   5145   }
   5146 
   5147   pc->phase = PP_PARSE_WALLET_DATA;
   5148 }
   5149 
   5150 
   5151 /**
   5152  * Custom cleanup routine for a `struct PayContext`.
   5153  *
   5154  * @param cls the `struct PayContext` to clean up.
   5155  */
   5156 static void
   5157 pay_context_cleanup (void *cls)
   5158 {
   5159   struct PayContext *pc = cls;
   5160 
   5161   if (NULL != pc->batch_deposits.timeout_task)
   5162   {
   5163     GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task);
   5164     pc->batch_deposits.timeout_task = NULL;
   5165   }
   5166   if (NULL != pc->check_contract.contract_terms_json)
   5167   {
   5168     json_decref (pc->check_contract.contract_terms_json);
   5169     pc->check_contract.contract_terms_json = NULL;
   5170   }
   5171   for (unsigned int i = 0; i<pc->parse_pay.coins_cnt; i++)
   5172   {
   5173     struct DepositConfirmation *dc = &pc->parse_pay.dc[i];
   5174 
   5175     TALER_denom_sig_free (&dc->cdd.denom_sig);
   5176     GNUNET_free (dc->exchange_url);
   5177   }
   5178   GNUNET_free (pc->parse_pay.dc);
   5179   for (unsigned int i = 0; i<pc->parse_pay.tokens_cnt; i++)
   5180   {
   5181     struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i];
   5182 
   5183     TALER_token_issue_sig_free (&tuc->unblinded_sig);
   5184   }
   5185   GNUNET_free (pc->parse_pay.tokens);
   5186   for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++)
   5187   {
   5188     struct ExchangeGroup *eg = pc->parse_pay.egs[i];
   5189 
   5190     if (NULL != eg->fo)
   5191       TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
   5192     if (NULL != eg->bdh)
   5193       TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh);
   5194     if (NULL != eg->keys)
   5195       TALER_EXCHANGE_keys_decref (eg->keys);
   5196     GNUNET_free (eg);
   5197   }
   5198   GNUNET_free (pc->parse_pay.egs);
   5199   if (NULL != pc->check_contract.contract_terms)
   5200   {
   5201     TALER_MERCHANT_contract_free (pc->check_contract.contract_terms);
   5202     pc->check_contract.contract_terms = NULL;
   5203   }
   5204   if (NULL != pc->response)
   5205   {
   5206     MHD_destroy_response (pc->response);
   5207     pc->response = NULL;
   5208   }
   5209   GNUNET_free (pc->parse_pay.session_id);
   5210   GNUNET_CONTAINER_DLL_remove (pc_head,
   5211                                pc_tail,
   5212                                pc);
   5213   GNUNET_free (pc->check_contract.pos_key);
   5214   GNUNET_free (pc->compute_money_pots.pots);
   5215   GNUNET_free (pc->compute_money_pots.increments);
   5216 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   5217   if (NULL != pc->parse_wallet_data.bkps)
   5218   {
   5219     for (size_t i = 0; i < pc->parse_wallet_data.num_bkps; i++)
   5220       GNUNET_CRYPTO_blinded_message_decref (
   5221         pc->parse_wallet_data.bkps[i].blinded_udi.blinded_message);
   5222     GNUNET_array_grow (pc->parse_wallet_data.bkps,
   5223                        pc->parse_wallet_data.num_bkps,
   5224                        0);
   5225   }
   5226   if (NULL != pc->parse_wallet_data.donau_keys)
   5227   {
   5228     DONAU_keys_decref (pc->parse_wallet_data.donau_keys);
   5229     pc->parse_wallet_data.donau_keys = NULL;
   5230   }
   5231   GNUNET_free (pc->parse_wallet_data.donau.donau_url);
   5232 #endif
   5233   for (unsigned int i = 0; i<pc->parse_wallet_data.token_envelopes_cnt; i++)
   5234   {
   5235     struct TokenEnvelope *ev
   5236       = &pc->parse_wallet_data.token_envelopes[i];
   5237 
   5238     GNUNET_CRYPTO_blinded_message_decref (ev->blinded_token.blinded_pub);
   5239   }
   5240   GNUNET_free (pc->parse_wallet_data.token_envelopes);
   5241   if (NULL != pc->output_tokens)
   5242   {
   5243     for (unsigned int i = 0; i<pc->output_tokens_len; i++)
   5244       if (NULL != pc->output_tokens[i].sig.signature)
   5245         GNUNET_CRYPTO_blinded_sig_decref (pc->output_tokens[i].sig.signature);
   5246     GNUNET_free (pc->output_tokens);
   5247     pc->output_tokens = NULL;
   5248   }
   5249   GNUNET_free (pc);
   5250 }
   5251 
   5252 
   5253 MHD_RESULT
   5254 TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh,
   5255                         struct MHD_Connection *connection,
   5256                         struct TMH_HandlerContext *hc)
   5257 {
   5258   struct PayContext *pc = hc->ctx;
   5259 
   5260   GNUNET_assert (NULL != hc->infix);
   5261   if (NULL == pc)
   5262   {
   5263     pc = GNUNET_new (struct PayContext);
   5264     pc->connection = connection;
   5265     pc->hc = hc;
   5266     pc->order_id = hc->infix;
   5267     hc->ctx = pc;
   5268     hc->cc = &pay_context_cleanup;
   5269     GNUNET_CONTAINER_DLL_insert (pc_head,
   5270                                  pc_tail,
   5271                                  pc);
   5272   }
   5273   while (1)
   5274   {
   5275     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5276                 "Processing /pay in phase %d\n",
   5277                 (int) pc->phase);
   5278     switch (pc->phase)
   5279     {
   5280     case PP_PARSE_PAY:
   5281       phase_parse_pay (pc);
   5282       break;
   5283     case PP_PARSE_WALLET_DATA:
   5284       phase_parse_wallet_data (pc);
   5285       break;
   5286     case PP_CHECK_CONTRACT:
   5287       phase_check_contract (pc);
   5288       break;
   5289     case PP_VALIDATE_TOKENS:
   5290       phase_validate_tokens (pc);
   5291       break;
   5292     case PP_CONTRACT_PAID:
   5293       phase_contract_paid (pc);
   5294       break;
   5295     case PP_COMPUTE_MONEY_POTS:
   5296       phase_compute_money_pots (pc);
   5297       break;
   5298     case PP_PAY_TRANSACTION:
   5299       phase_execute_pay_transaction (pc);
   5300       break;
   5301     case PP_REQUEST_DONATION_RECEIPT:
   5302 #ifdef HAVE_DONAU_DONAU_SERVICE_H
   5303       phase_request_donation_receipt (pc);
   5304 #else
   5305       pc->phase++;
   5306 #endif
   5307       break;
   5308     case PP_FINAL_OUTPUT_TOKEN_PROCESSING:
   5309       phase_final_output_token_processing (pc);
   5310       break;
   5311     case PP_PAYMENT_NOTIFICATION:
   5312       phase_payment_notification (pc);
   5313       break;
   5314     case PP_SUCCESS_RESPONSE:
   5315       phase_success_response (pc);
   5316       break;
   5317     case PP_BATCH_DEPOSITS:
   5318       phase_batch_deposits (pc);
   5319       break;
   5320     case PP_RETURN_RESPONSE:
   5321       phase_return_response (pc);
   5322       break;
   5323     case PP_FAIL_LEGAL_REASONS:
   5324       phase_fail_for_legal_reasons (pc);
   5325       break;
   5326     case PP_END_YES:
   5327       return MHD_YES;
   5328     case PP_END_NO:
   5329       return MHD_NO;
   5330     default:
   5331       /* should not be reachable */
   5332       GNUNET_assert (0);
   5333       return MHD_NO;
   5334     }
   5335     switch (pc->suspended)
   5336     {
   5337     case GNUNET_SYSERR:
   5338       /* during shutdown, we don't generate any more replies */
   5339       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5340                   "Processing /pay ends due to shutdown in phase %d\n",
   5341                   (int) pc->phase);
   5342       return MHD_NO;
   5343     case GNUNET_NO:
   5344       /* continue to next phase */
   5345       break;
   5346     case GNUNET_YES:
   5347       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5348                   "Processing /pay suspended in phase %d\n",
   5349                   (int) pc->phase);
   5350       return MHD_YES;
   5351     }
   5352   }
   5353   /* impossible to get here */
   5354   GNUNET_assert (0);
   5355   return MHD_YES;
   5356 }
   5357 
   5358 
   5359 /* end of taler-merchant-httpd_post-orders-ORDER_ID-pay.c */