merchant

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

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


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