merchant

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

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


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