merchant

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

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


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