merchant

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

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


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