merchant

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

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


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