merchant

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

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


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