merchant

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

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


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