taler-merchant-httpd_post-orders-ORDER_ID-pay.c (169684B)
1 /* 2 This file is part of TALER 3 (C) 2014-2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Affero General Public License as 7 published by the Free Software Foundation; either version 3, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file src/backend/taler-merchant-httpd_post-orders-ORDER_ID-pay.c 22 * @brief handling of POST /orders/$ID/pay requests 23 * @author Marcello Stanisci 24 * @author Christian Grothoff 25 * @author Florian Dold 26 */ 27 #include "platform.h" 28 struct ExchangeGroup; 29 #define TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE struct ExchangeGroup 30 #include <gnunet/gnunet_common.h> 31 #include <gnunet/gnunet_db_lib.h> 32 #include <gnunet/gnunet_json_lib.h> 33 #include <gnunet/gnunet_time_lib.h> 34 #include <jansson.h> 35 #include <microhttpd.h> 36 #include <stddef.h> 37 #include <stdint.h> 38 #include <string.h> 39 #include <taler/taler_dbevents.h> 40 #include <taler/taler_error_codes.h> 41 #include <taler/taler_signatures.h> 42 #include <taler/taler_json_lib.h> 43 #include <taler/taler_exchange_service.h> 44 #include "taler-merchant-httpd.h" 45 #include "taler-merchant-httpd_exchanges.h" 46 #include "taler-merchant-httpd_get-exchanges.h" 47 #include "taler-merchant-httpd_helper.h" 48 #include "taler-merchant-httpd_post-orders-ORDER_ID-pay.h" 49 #include "taler-merchant-httpd_get-private-orders.h" 50 #include "taler/taler_merchant_util.h" 51 #include "merchantdb_lib.h" 52 #include <donau/donau_service.h> 53 #include <donau/donau_util.h> 54 #include <donau/donau_json_lib.h> 55 #include "merchant-database/update_money_pot_totals.h" 56 #include "merchant-database/insert_deposit.h" 57 #include "merchant-database/insert_deposit_confirmation.h" 58 #include "merchant-database/insert_issued_token.h" 59 #include "merchant-database/insert_order_token_blinded_sig.h" 60 #include "merchant-database/insert_used_token.h" 61 #include "merchant-database/get_contract_terms_pos.h" 62 #include "merchant-database/iterate_deposits.h" 63 #include "merchant-database/iterate_deposits_by_order.h" 64 #include "merchant-database/get_donau_instance_by_url.h" 65 #include "merchant-database/iterate_refunds.h" 66 #include "merchant-database/set_instance.h" 67 #include "merchant-database/iterate_used_tokens_by_order.h" 68 #include "merchant-database/get_token_family_key.h" 69 #include "merchant-database/update_to_contract_terms_paid.h" 70 #include "merchant-database/iterate_order_token_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_token_blinded_sig")) 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_token_blinded_sig ( 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_used_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_iterate_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_iterate_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_update_to_contract_terms_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_update_money_pot_totals ( 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 "update_money_pot_totals")); 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_get_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 must exist: the LEFT JOIN in get_token_family_key() 3777 only yields a NULL private key if no key covers the validity 3778 period *and* survives until the pay deadline, and POST /orders 3779 guarantees exactly that before it commits the contract terms 3780 (it extends the retention of an existing key or mints a new 3781 one, see #11692). Kept as a safety net. */ 3782 GNUNET_break (0); 3783 pay_end (pc, 3784 TALER_MHD_reply_with_error ( 3785 pc->connection, 3786 MHD_HTTP_INTERNAL_SERVER_ERROR, 3787 TALER_EC_GENERIC_DB_INVARIANT_FAILURE, 3788 "private token family key not found")); 3789 return GNUNET_NO; 3790 3791 } 3792 3793 /* Depending on the token family, decide if the token envelope 3794 * is mandatory or optional. (Simplified logic here: adapt as needed.) */ 3795 mandatory = test_tfk_mandatory (details.token_family.kind); 3796 /* Actually sign the number of token envelopes specified in 'count'. 3797 * 'output_index' is the offset into the output_tokens while 3798 * 'wallet_index' is the offset into parse_wallet_data.token_envelopes */ 3799 if (GNUNET_OK != 3800 sign_token_envelopes (pc, 3801 key, 3802 &details.priv, 3803 mandatory, 3804 wallet_index, 3805 output_index, 3806 output->details.token.count)) 3807 { 3808 /* sign_token_envelopes() already queued up an error via pay_end() */ 3809 GNUNET_break_op (0); 3810 return GNUNET_NO; 3811 } 3812 GNUNET_CRYPTO_blind_sign_priv_decref (details.priv.private_key); 3813 return GNUNET_OK; 3814 } 3815 3816 3817 /** 3818 * Handle checks for contract output of type 3819 * #TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT. 3820 * 3821 * @param pc context for the pay request 3822 * @param output the contract output describing the donation receipt requirement 3823 * @return #GNUNET_OK on success, 3824 * #GNUNET_NO if an error was already queued 3825 */ 3826 static enum GNUNET_GenericReturnValue 3827 handle_output_donation_receipt ( 3828 struct PayContext *pc, 3829 const struct TALER_MERCHANT_ContractOutput *output) 3830 { 3831 enum GNUNET_GenericReturnValue ret; 3832 3833 ret = DONAU_get_donation_amount_from_bkps ( 3834 pc->parse_wallet_data.donau_keys, 3835 pc->parse_wallet_data.bkps, 3836 pc->parse_wallet_data.num_bkps, 3837 pc->parse_wallet_data.donau.donation_year, 3838 &pc->parse_wallet_data.donation_amount); 3839 switch (ret) 3840 { 3841 case GNUNET_SYSERR: 3842 GNUNET_break (0); 3843 pay_end (pc, 3844 TALER_MHD_reply_with_error ( 3845 pc->connection, 3846 MHD_HTTP_INTERNAL_SERVER_ERROR, 3847 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3848 NULL)); 3849 return GNUNET_NO; 3850 case GNUNET_NO: 3851 GNUNET_break_op (0); 3852 pay_end (pc, 3853 TALER_MHD_reply_with_error ( 3854 pc->connection, 3855 MHD_HTTP_BAD_REQUEST, 3856 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3857 "inconsistent bkps / donau keys")); 3858 return GNUNET_NO; 3859 case GNUNET_OK: 3860 break; 3861 } 3862 3863 if (GNUNET_OK != 3864 TALER_amount_cmp_currency (&pc->parse_wallet_data.donation_amount, 3865 &output->details.donation_receipt.amount)) 3866 { 3867 GNUNET_break_op (0); 3868 pay_end (pc, 3869 TALER_MHD_reply_with_error ( 3870 pc->connection, 3871 MHD_HTTP_BAD_REQUEST, 3872 TALER_EC_GENERIC_CURRENCY_MISMATCH, 3873 output->details.donation_receipt.amount.currency)); 3874 return GNUNET_NO; 3875 } 3876 3877 if (0 != 3878 TALER_amount_cmp (&pc->parse_wallet_data.donation_amount, 3879 &output->details.donation_receipt.amount)) 3880 { 3881 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3882 "Wallet amount: %s\n", 3883 TALER_amount2s (&pc->parse_wallet_data.donation_amount)); 3884 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3885 "Donation receipt amount: %s\n", 3886 TALER_amount2s (&output->details.donation_receipt.amount)); 3887 GNUNET_break_op (0); 3888 pay_end (pc, 3889 TALER_MHD_reply_with_error ( 3890 pc->connection, 3891 MHD_HTTP_CONFLICT, 3892 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH, 3893 "donation amount mismatch")); 3894 return GNUNET_NO; 3895 } 3896 { 3897 struct TALER_Amount receipts_to_date; 3898 3899 if (0 > 3900 TALER_amount_add (&receipts_to_date, 3901 &pc->parse_wallet_data.charity_receipts_to_date, 3902 &pc->parse_wallet_data.donation_amount)) 3903 { 3904 GNUNET_break (0); 3905 pay_end (pc, 3906 TALER_MHD_reply_with_error (pc->connection, 3907 MHD_HTTP_INTERNAL_SERVER_ERROR, 3908 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 3909 "adding donation amount")); 3910 return GNUNET_NO; 3911 } 3912 3913 if (1 == 3914 TALER_amount_cmp (&receipts_to_date, 3915 &pc->parse_wallet_data.charity_max_per_year)) 3916 { 3917 GNUNET_break_op (0); 3918 pay_end (pc, 3919 TALER_MHD_reply_with_error (pc->connection, 3920 MHD_HTTP_CONFLICT, 3921 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH, 3922 "donation limit exceeded")); 3923 return GNUNET_NO; 3924 } 3925 pc->parse_wallet_data.charity_receipts_to_date = receipts_to_date; 3926 } 3927 return GNUNET_OK; 3928 } 3929 3930 3931 /** 3932 * Count tokens produced by an output. 3933 * 3934 * @param pc pay context 3935 * @param output output to consider 3936 * @returns number of output tokens 3937 */ 3938 static unsigned int 3939 count_output_tokens (const struct PayContext *pc, 3940 const struct TALER_MERCHANT_ContractOutput *output) 3941 { 3942 switch (output->type) 3943 { 3944 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 3945 GNUNET_assert (0); 3946 break; 3947 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 3948 return output->details.token.count; 3949 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 3950 return pc->parse_wallet_data.num_bkps; 3951 } 3952 /* Not reached. */ 3953 GNUNET_assert (0); 3954 } 3955 3956 3957 /** 3958 * Validate tokens and token envelopes. First, we check if all tokens listed 3959 * in the 'inputs' array of the selected choice are present in the 'tokens' 3960 * array of the request. Then, we validate the signatures of each provided 3961 * token. 3962 * 3963 * @param[in,out] pc context we use to handle the payment 3964 */ 3965 static void 3966 phase_validate_tokens (struct PayContext *pc) 3967 { 3968 /* We haven't seen a donau output yet. */ 3969 pc->validate_tokens.donau_output_index = -1; 3970 3971 switch (pc->check_contract.contract_terms->pc->base->version) 3972 { 3973 case TALER_MERCHANT_CONTRACT_VERSION_0: 3974 /* No tokens to validate */ 3975 pc->phase = PP_COMPUTE_MONEY_POTS; 3976 pc->validate_tokens.max_fee 3977 = pc->check_contract.contract_terms->pc->details.v0.max_fee; 3978 pc->validate_tokens.brutto 3979 = pc->check_contract.contract_terms->pc->details.v0.brutto; 3980 break; 3981 case TALER_MERCHANT_CONTRACT_VERSION_1: 3982 { 3983 const struct TALER_MERCHANT_ContractChoice *selected 3984 = &pc->check_contract.contract_terms->pc->details.v1.choices[ 3985 pc->parse_wallet_data.choice_index]; 3986 unsigned int output_off; 3987 unsigned int wallet_off; 3988 unsigned int cnt; 3989 3990 pc->validate_tokens.max_fee = selected->max_fee; 3991 pc->validate_tokens.brutto = selected->amount; 3992 wallet_off = 0; 3993 for (unsigned int i = 0; i<selected->inputs_len; i++) 3994 { 3995 const struct TALER_MERCHANT_ContractInput *input 3996 = &selected->inputs[i]; 3997 const struct TALER_MERCHANT_ContractTokenFamily *family; 3998 3999 switch (input->type) 4000 { 4001 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID: 4002 GNUNET_break (0); 4003 pay_end (pc, 4004 TALER_MHD_reply_with_error ( 4005 pc->connection, 4006 MHD_HTTP_BAD_REQUEST, 4007 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4008 "input token type not valid")); 4009 return; 4010 #if FUTURE 4011 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN: 4012 GNUNET_break (0); 4013 pay_end (pc, 4014 TALER_MHD_reply_with_error ( 4015 pc->connection, 4016 MHD_HTTP_NOT_IMPLEMENTED, 4017 TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE, 4018 "token type not yet supported")); 4019 return; 4020 #endif 4021 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN: 4022 family = find_family (pc, 4023 input->details.token.token_family_slug); 4024 if (NULL == family) 4025 { 4026 /* this should never happen, since the choices and 4027 token families are validated on insert. */ 4028 GNUNET_break (0); 4029 pay_end (pc, 4030 TALER_MHD_reply_with_error ( 4031 pc->connection, 4032 MHD_HTTP_INTERNAL_SERVER_ERROR, 4033 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 4034 "token family not found in order")); 4035 return; 4036 } 4037 if (GNUNET_NO == 4038 find_valid_input_tokens (pc, 4039 family, 4040 wallet_off, 4041 input->details.token.count)) 4042 { 4043 /* Error is already scheduled from find_valid_input_token. */ 4044 return; 4045 } 4046 wallet_off += input->details.token.count; 4047 } 4048 } 4049 4050 /* calculate pc->output_tokens_len */ 4051 output_off = 0; 4052 for (unsigned int i = 0; i<selected->outputs_len; i++) 4053 { 4054 const struct TALER_MERCHANT_ContractOutput *output 4055 = &selected->outputs[i]; 4056 4057 switch (output->type) 4058 { 4059 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 4060 GNUNET_assert (0); 4061 break; 4062 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 4063 cnt = output->details.token.count; 4064 if (output_off + cnt < output_off) 4065 { 4066 GNUNET_break_op (0); 4067 pay_end (pc, 4068 TALER_MHD_reply_with_error ( 4069 pc->connection, 4070 MHD_HTTP_BAD_REQUEST, 4071 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4072 "output token counter overflow")); 4073 return; 4074 } 4075 output_off += cnt; 4076 break; 4077 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 4078 /* check that this output type appears at most once */ 4079 if (pc->validate_tokens.donau_output_index >= 0) 4080 { 4081 /* This should have been prevented when the 4082 contract was initially created */ 4083 GNUNET_break (0); 4084 pay_end (pc, 4085 TALER_MHD_reply_with_error ( 4086 pc->connection, 4087 MHD_HTTP_INTERNAL_SERVER_ERROR, 4088 TALER_EC_GENERIC_DB_INVARIANT_FAILURE, 4089 "two donau output sets in same contract")); 4090 return; 4091 } 4092 pc->validate_tokens.donau_output_index = i; 4093 if (output_off + pc->parse_wallet_data.num_bkps < output_off) 4094 { 4095 GNUNET_break_op (0); 4096 pay_end (pc, 4097 TALER_MHD_reply_with_error ( 4098 pc->connection, 4099 MHD_HTTP_BAD_REQUEST, 4100 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4101 "output token counter overflow")); 4102 return; 4103 } 4104 output_off += pc->parse_wallet_data.num_bkps; 4105 break; 4106 } 4107 } 4108 4109 4110 pc->output_tokens_len = output_off; 4111 pc->output_tokens 4112 = GNUNET_new_array (pc->output_tokens_len, 4113 struct SignedOutputToken); 4114 4115 /* calculate pc->output_tokens[].output_index */ 4116 output_off = 0; /* index into output_tokens */ 4117 for (unsigned int i = 0; i<selected->outputs_len; i++) 4118 { 4119 const struct TALER_MERCHANT_ContractOutput *output 4120 = &selected->outputs[i]; 4121 4122 cnt = count_output_tokens (pc, 4123 output); 4124 for (unsigned int j = 0; j<cnt; j++) 4125 pc->output_tokens[output_off + j].output_index = i; 4126 output_off += cnt; 4127 } 4128 4129 /* compute non-donau outputs */ 4130 output_off = 0; /* index into output_tokens */ 4131 wallet_off = 0; /* index into parse_wallet_data.token_envelopes */ 4132 for (unsigned int i = 0; i<selected->outputs_len; i++) 4133 { 4134 const struct TALER_MERCHANT_ContractOutput *output 4135 = &selected->outputs[i]; 4136 4137 switch (output->type) 4138 { 4139 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 4140 GNUNET_assert (0); 4141 break; 4142 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 4143 cnt = output->details.token.count; 4144 GNUNET_assert (output_off + cnt 4145 <= pc->output_tokens_len); 4146 if (GNUNET_OK != 4147 handle_output_token (pc, 4148 wallet_off, 4149 output, 4150 output_off)) 4151 { 4152 /* Error is already scheduled from handle_output_token. */ 4153 return; 4154 } 4155 output_off += cnt; 4156 wallet_off += cnt; 4157 break; 4158 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 4159 if ( (0 != pc->parse_wallet_data.num_bkps) && 4160 (GNUNET_OK != 4161 handle_output_donation_receipt (pc, 4162 output)) ) 4163 { 4164 /* Error is already scheduled from handle_output_donation_receipt. */ 4165 return; 4166 } 4167 output_off += pc->parse_wallet_data.num_bkps; 4168 /* Note: wallet_off NOT increased, as bkps are 4169 separate from parse_wallet_data.token_envelopes */ 4170 continue; 4171 } /* switch on output token */ 4172 } /* for all output token types */ 4173 } /* case contract v1 */ 4174 break; 4175 } /* switch on contract type */ 4176 4177 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4178 { 4179 const struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 4180 4181 if (GNUNET_OK != 4182 TALER_amount_cmp_currency (&dc->cdd.amount, 4183 &pc->validate_tokens.brutto)) 4184 { 4185 GNUNET_break_op (0); 4186 pay_end (pc, 4187 TALER_MHD_reply_with_error ( 4188 pc->connection, 4189 MHD_HTTP_CONFLICT, 4190 TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, 4191 pc->validate_tokens.brutto.currency)); 4192 return; 4193 } 4194 } 4195 4196 pc->phase = PP_COMPUTE_MONEY_POTS; 4197 } 4198 4199 4200 /** 4201 * Function called with information about a coin that was deposited. 4202 * Checks if this coin is in our list of deposits as well. 4203 * 4204 * @param cls closure with our `struct PayContext *` 4205 * @param deposit_serial which deposit operation is this about 4206 * @param exchange_url URL of the exchange that issued the coin 4207 * @param h_wire hash of merchant's wire details 4208 * @param deposit_timestamp when was the deposit made 4209 * @param amount_with_fee amount the exchange will deposit for this coin 4210 * @param deposit_fee fee the exchange will charge for this coin 4211 * @param coin_pub public key of the coin 4212 */ 4213 static void 4214 deposit_paid_check ( 4215 void *cls, 4216 uint64_t deposit_serial, 4217 const char *exchange_url, 4218 const struct TALER_MerchantWireHashP *h_wire, 4219 struct GNUNET_TIME_Timestamp deposit_timestamp, 4220 const struct TALER_Amount *amount_with_fee, 4221 const struct TALER_Amount *deposit_fee, 4222 const struct TALER_CoinSpendPublicKeyP *coin_pub) 4223 { 4224 struct PayContext *pc = cls; 4225 4226 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4227 { 4228 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4229 4230 if ( (0 == 4231 GNUNET_memcmp (&dci->cdd.coin_pub, 4232 coin_pub)) && 4233 (0 == 4234 strcmp (dci->exchange_url, 4235 exchange_url)) && 4236 (GNUNET_YES == 4237 TALER_amount_cmp_currency (&dci->cdd.amount, 4238 amount_with_fee)) && 4239 (0 == 4240 TALER_amount_cmp (&dci->cdd.amount, 4241 amount_with_fee)) ) 4242 { 4243 dci->matched_in_db = true; 4244 break; 4245 } 4246 } 4247 } 4248 4249 4250 /** 4251 * Function called with information about a token that was spent. 4252 * FIXME: Replace this with a more specific function for this cb 4253 * 4254 * @param cls closure with `struct PayContext *` 4255 * @param spent_token_serial "serial" of the spent token unused 4256 * @param h_contract_terms hash of the contract terms unused 4257 * @param h_issue_pub hash of the token issue public key unused 4258 * @param use_pub public key of the token 4259 * @param use_sig signature of the token 4260 * @param issue_sig signature of the token issue 4261 */ 4262 static void 4263 input_tokens_paid_check ( 4264 void *cls, 4265 uint64_t spent_token_serial, 4266 const struct TALER_PrivateContractHashP *h_contract_terms, 4267 const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub, 4268 const struct TALER_TokenUsePublicKeyP *use_pub, 4269 const struct TALER_TokenUseSignatureP *use_sig, 4270 const struct TALER_TokenIssueSignature *issue_sig) 4271 { 4272 struct PayContext *pc = cls; 4273 4274 for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++) 4275 { 4276 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 4277 4278 if ( (0 == 4279 GNUNET_memcmp (&tuc->pub, 4280 use_pub)) && 4281 (0 == 4282 GNUNET_memcmp (&tuc->sig, 4283 use_sig)) && 4284 (0 == 4285 GNUNET_memcmp (&tuc->unblinded_sig, 4286 issue_sig)) ) 4287 { 4288 tuc->found_in_db = true; 4289 break; 4290 } 4291 } 4292 } 4293 4294 4295 /** 4296 * Small helper function to append an output token signature from db 4297 * 4298 * @param cls closure with `struct PayContext *` 4299 * @param h_issue hash of the token 4300 * @param sig signature of the token 4301 */ 4302 static void 4303 append_output_token_sig (void *cls, 4304 struct GNUNET_HashCode *h_issue, 4305 struct GNUNET_CRYPTO_BlindedSignature *sig) 4306 { 4307 struct PayContext *pc = cls; 4308 struct TALER_MERCHANT_ContractChoice *choice; 4309 const struct TALER_MERCHANT_ContractOutput *output; 4310 struct SignedOutputToken out; 4311 unsigned int cnt; 4312 4313 memset (&out, 4314 0, 4315 sizeof (out)); 4316 GNUNET_assert (TALER_MERCHANT_CONTRACT_VERSION_1 == 4317 pc->check_contract.contract_terms->pc->base->version); 4318 choice = &pc->check_contract.contract_terms->pc->details.v1 4319 .choices[pc->parse_wallet_data.choice_index]; 4320 output = &choice->outputs[pc->output_index_gen]; 4321 cnt = count_output_tokens (pc, 4322 output); 4323 out.output_index = pc->output_index_gen; 4324 out.h_issue.hash = *h_issue; 4325 out.sig.signature = sig; 4326 GNUNET_CRYPTO_blind_sig_incref (sig); 4327 GNUNET_array_append (pc->output_tokens, 4328 pc->output_tokens_len, 4329 out); 4330 /* Go to next output once we've output all tokens for the current one. */ 4331 pc->output_token_cnt++; 4332 if (pc->output_token_cnt >= cnt) 4333 { 4334 pc->output_token_cnt = 0; 4335 pc->output_index_gen++; 4336 } 4337 } 4338 4339 4340 /** 4341 * Handle case where contract was already paid. Either decides 4342 * the payment is idempotent, or refunds the excess payment. 4343 * 4344 * @param[in,out] pc context we use to handle the payment 4345 */ 4346 static void 4347 phase_contract_paid (struct PayContext *pc) 4348 { 4349 json_t *refunds; 4350 bool unmatched = false; 4351 4352 { 4353 enum GNUNET_DB_QueryStatus qs; 4354 4355 qs = TALER_MERCHANTDB_iterate_deposits_by_order (TMH_db, 4356 pc->check_contract.order_serial, 4357 &deposit_paid_check, 4358 pc); 4359 /* Since orders with choices can have a price of zero, 4360 0 is also a valid query state */ 4361 if (qs < 0) 4362 { 4363 GNUNET_break (0); 4364 pay_end (pc, 4365 TALER_MHD_reply_with_error ( 4366 pc->connection, 4367 MHD_HTTP_INTERNAL_SERVER_ERROR, 4368 TALER_EC_GENERIC_DB_FETCH_FAILED, 4369 "iterate_deposits_by_order")); 4370 return; 4371 } 4372 } 4373 for (size_t i = 0; 4374 i<pc->parse_pay.coins_cnt && ! unmatched; 4375 i++) 4376 { 4377 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4378 4379 if (! dci->matched_in_db) 4380 unmatched = true; 4381 } 4382 /* Check if provided input tokens match token in the database */ 4383 { 4384 enum GNUNET_DB_QueryStatus qs; 4385 4386 /* FIXME-Optimization: Maybe use h_contract instead of order_serial here? */ 4387 qs = TALER_MERCHANTDB_iterate_used_tokens_by_order (TMH_db, 4388 pc->check_contract.order_serial, 4389 &input_tokens_paid_check, 4390 pc); 4391 4392 if (qs < 0) 4393 { 4394 GNUNET_break (0); 4395 pay_end (pc, 4396 TALER_MHD_reply_with_error ( 4397 pc->connection, 4398 MHD_HTTP_INTERNAL_SERVER_ERROR, 4399 TALER_EC_GENERIC_DB_FETCH_FAILED, 4400 "iterate_used_tokens_by_order")); 4401 return; 4402 } 4403 } 4404 for (size_t i = 0; i<pc->parse_pay.tokens_cnt && ! unmatched; i++) 4405 { 4406 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 4407 4408 if (! tuc->found_in_db) 4409 unmatched = true; 4410 } 4411 4412 /* In this part we are fetching token_sigs related output */ 4413 if (! unmatched) 4414 { 4415 /* Everything fine, idempotent request, generate response immediately */ 4416 enum GNUNET_DB_QueryStatus qs; 4417 4418 pc->output_index_gen = 0; 4419 qs = TALER_MERCHANTDB_iterate_order_token_blinded_sigs ( 4420 TMH_db, 4421 pc->order_id, 4422 &append_output_token_sig, 4423 pc); 4424 if (0 > qs) 4425 { 4426 GNUNET_break (0); 4427 pay_end (pc, 4428 TALER_MHD_reply_with_error ( 4429 pc->connection, 4430 MHD_HTTP_INTERNAL_SERVER_ERROR, 4431 TALER_EC_GENERIC_DB_FETCH_FAILED, 4432 "iterate_order_token_blinded_sigs")); 4433 return; 4434 } 4435 4436 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4437 "Idempotent pay request for order `%s', signing again\n", 4438 pc->order_id); 4439 pc->phase = PP_SUCCESS_RESPONSE; 4440 return; 4441 } 4442 /* Conflict, double-payment detected! */ 4443 /* FIXME-#8674: What should we do with input tokens? 4444 Currently there is no refund for tokens. */ 4445 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4446 "Client attempted to pay extra for already paid order `%s'\n", 4447 pc->order_id); 4448 refunds = json_array (); 4449 GNUNET_assert (NULL != refunds); 4450 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4451 { 4452 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4453 struct TALER_MerchantSignatureP merchant_sig; 4454 4455 if (dci->matched_in_db) 4456 continue; 4457 TALER_merchant_refund_sign (&dci->cdd.coin_pub, 4458 &pc->check_contract.h_contract_terms, 4459 0, /* rtransaction id */ 4460 &dci->cdd.amount, 4461 &pc->hc->instance->merchant_priv, 4462 &merchant_sig); 4463 GNUNET_assert ( 4464 0 == 4465 json_array_append_new ( 4466 refunds, 4467 GNUNET_JSON_PACK ( 4468 GNUNET_JSON_pack_data_auto ( 4469 "coin_pub", 4470 &dci->cdd.coin_pub), 4471 GNUNET_JSON_pack_data_auto ( 4472 "merchant_sig", 4473 &merchant_sig), 4474 TALER_JSON_pack_amount ("amount", 4475 &dci->cdd.amount), 4476 GNUNET_JSON_pack_uint64 ("rtransaction_id", 4477 0)))); 4478 } 4479 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4480 "Generating JSON response with code %d\n", 4481 (int) TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID); 4482 pay_end (pc, 4483 TALER_MHD_REPLY_JSON_PACK ( 4484 pc->connection, 4485 MHD_HTTP_CONFLICT, 4486 TALER_MHD_PACK_EC ( 4487 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID), 4488 GNUNET_JSON_pack_array_steal ("refunds", 4489 refunds))); 4490 } 4491 4492 4493 /** 4494 * Check the database state for the given order. 4495 * Schedules an error response in the connection on failure. 4496 * 4497 * @param[in,out] pc context we use to handle the payment 4498 */ 4499 static void 4500 phase_check_contract (struct PayContext *pc) 4501 { 4502 /* obtain contract terms */ 4503 enum GNUNET_DB_QueryStatus qs; 4504 bool paid = false; 4505 4506 if (NULL != pc->check_contract.contract_terms_json) 4507 { 4508 json_decref (pc->check_contract.contract_terms_json); 4509 pc->check_contract.contract_terms_json = NULL; 4510 } 4511 if (NULL != pc->check_contract.contract_terms) 4512 { 4513 TALER_MERCHANT_contract_free (pc->check_contract.contract_terms); 4514 pc->check_contract.contract_terms = NULL; 4515 } 4516 qs = TALER_MERCHANTDB_get_contract_terms_pos ( 4517 TMH_db, 4518 pc->hc->instance->settings.id, 4519 pc->order_id, 4520 &pc->check_contract.contract_terms_json, 4521 &pc->check_contract.order_serial, 4522 &paid, 4523 NULL, 4524 &pc->check_contract.pos_key, 4525 &pc->check_contract.pos_alg); 4526 if (0 > qs) 4527 { 4528 /* single, read-only SQL statements should never cause 4529 serialization problems */ 4530 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 4531 /* Always report on hard error to enable diagnostics */ 4532 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 4533 pay_end (pc, 4534 TALER_MHD_reply_with_error ( 4535 pc->connection, 4536 MHD_HTTP_INTERNAL_SERVER_ERROR, 4537 TALER_EC_GENERIC_DB_FETCH_FAILED, 4538 "contract terms")); 4539 return; 4540 } 4541 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 4542 { 4543 pay_end (pc, 4544 TALER_MHD_reply_with_error ( 4545 pc->connection, 4546 MHD_HTTP_NOT_FOUND, 4547 TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN, 4548 pc->order_id)); 4549 return; 4550 } 4551 /* hash contract (needed later) */ 4552 #if DEBUG 4553 json_dumpf (pc->check_contract.contract_terms_json, 4554 stderr, 4555 JSON_INDENT (2)); 4556 #endif 4557 if (GNUNET_OK != 4558 TALER_JSON_contract_hash (pc->check_contract.contract_terms_json, 4559 &pc->check_contract.h_contract_terms)) 4560 { 4561 GNUNET_break (0); 4562 pay_end (pc, 4563 TALER_MHD_reply_with_error ( 4564 pc->connection, 4565 MHD_HTTP_INTERNAL_SERVER_ERROR, 4566 TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH, 4567 NULL)); 4568 return; 4569 } 4570 4571 /* Parse the contract terms even for paid orders, 4572 as later phases need it. */ 4573 4574 pc->check_contract.contract_terms = TALER_MERCHANT_contract_parse ( 4575 pc->check_contract.contract_terms_json); 4576 4577 if (NULL == pc->check_contract.contract_terms) 4578 { 4579 /* invalid contract */ 4580 GNUNET_break (0); 4581 pay_end (pc, 4582 TALER_MHD_reply_with_error ( 4583 pc->connection, 4584 MHD_HTTP_INTERNAL_SERVER_ERROR, 4585 TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, 4586 pc->order_id)); 4587 return; 4588 } 4589 4590 if (paid) 4591 { 4592 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4593 "Order `%s' paid, checking for double-payment\n", 4594 pc->order_id); 4595 pc->phase = PP_CONTRACT_PAID; 4596 return; 4597 } 4598 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4599 "Handling payment for order `%s' with contract hash `%s'\n", 4600 pc->order_id, 4601 GNUNET_h2s (&pc->check_contract.h_contract_terms.hash)); 4602 4603 /* Check fundamentals */ 4604 { 4605 switch (pc->check_contract.contract_terms->pc->base->version) 4606 { 4607 case TALER_MERCHANT_CONTRACT_VERSION_0: 4608 { 4609 if (pc->parse_wallet_data.choice_index > 0) 4610 { 4611 GNUNET_break (0); 4612 pay_end (pc, 4613 TALER_MHD_reply_with_error ( 4614 pc->connection, 4615 MHD_HTTP_BAD_REQUEST, 4616 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS, 4617 "contract terms v0 has no choices")); 4618 return; 4619 } 4620 } 4621 break; 4622 case TALER_MERCHANT_CONTRACT_VERSION_1: 4623 { 4624 if (pc->parse_wallet_data.choice_index < 0) 4625 { 4626 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4627 "Order `%s' has non-empty choices array but" 4628 "request is missing 'choice_index' field\n", 4629 pc->order_id); 4630 GNUNET_break (0); 4631 pay_end (pc, 4632 TALER_MHD_reply_with_error ( 4633 pc->connection, 4634 MHD_HTTP_BAD_REQUEST, 4635 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING, 4636 NULL)); 4637 return; 4638 } 4639 if (pc->parse_wallet_data.choice_index >= 4640 pc->check_contract.contract_terms->pc->details.v1.choices_len) 4641 { 4642 GNUNET_log ( 4643 GNUNET_ERROR_TYPE_INFO, 4644 "Order `%s' has choices array with %u elements but " 4645 "request has 'choice_index' field with value %d\n", 4646 pc->order_id, 4647 pc->check_contract.contract_terms->pc->details.v1.choices_len, 4648 pc->parse_wallet_data.choice_index); 4649 GNUNET_break (0); 4650 pay_end (pc, 4651 TALER_MHD_reply_with_error ( 4652 pc->connection, 4653 MHD_HTTP_BAD_REQUEST, 4654 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS, 4655 NULL)); 4656 return; 4657 } 4658 } 4659 break; 4660 default: 4661 GNUNET_break (0); 4662 pay_end (pc, 4663 TALER_MHD_reply_with_error ( 4664 pc->connection, 4665 MHD_HTTP_INTERNAL_SERVER_ERROR, 4666 TALER_EC_GENERIC_DB_FETCH_FAILED, 4667 "contract 'version' in database not supported by this backend") 4668 ); 4669 return; 4670 } 4671 } 4672 4673 if (GNUNET_TIME_timestamp_cmp ( 4674 pc->check_contract.contract_terms->pc->wire_deadline, 4675 <, 4676 pc->check_contract.contract_terms->pc->refund_deadline)) 4677 { 4678 /* This should already have been checked when creating the order! */ 4679 GNUNET_break (0); 4680 pay_end (pc, 4681 TALER_MHD_reply_with_error ( 4682 pc->connection, 4683 MHD_HTTP_INTERNAL_SERVER_ERROR, 4684 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE, 4685 NULL)); 4686 return; 4687 } 4688 if (GNUNET_TIME_absolute_is_past ( 4689 pc->check_contract.contract_terms->pc->pay_deadline.abs_time)) 4690 { 4691 /* too late */ 4692 pay_end (pc, 4693 TALER_MHD_reply_with_error ( 4694 pc->connection, 4695 MHD_HTTP_GONE, 4696 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED, 4697 NULL)); 4698 return; 4699 } 4700 4701 /* Make sure wire method (still) exists for this instance */ 4702 { 4703 struct TMH_WireMethod *wm; 4704 4705 wm = pc->hc->instance->wm_head; 4706 while ( (NULL != wm) && 4707 (0 != 4708 GNUNET_memcmp ( 4709 &pc->check_contract.contract_terms->pc->h_wire, 4710 &wm->h_wire)) ) 4711 wm = wm->next; 4712 if (NULL == wm) 4713 { 4714 GNUNET_break (0); 4715 pay_end (pc, 4716 TALER_MHD_reply_with_error ( 4717 pc->connection, 4718 MHD_HTTP_INTERNAL_SERVER_ERROR, 4719 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN, 4720 NULL)); 4721 return; 4722 } 4723 pc->check_contract.wm = wm; 4724 } 4725 pc->phase = PP_VALIDATE_TOKENS; 4726 } 4727 4728 4729 /** 4730 * Try to parse the wallet_data object of the pay request into 4731 * the given context. Schedules an error response in the connection 4732 * on failure. 4733 * 4734 * @param[in,out] pc context we use to handle the payment 4735 */ 4736 static void 4737 phase_parse_wallet_data (struct PayContext *pc) 4738 { 4739 const json_t *tokens_evs; 4740 const json_t *donau_obj; 4741 4742 struct GNUNET_JSON_Specification spec[] = { 4743 GNUNET_JSON_spec_mark_optional ( 4744 GNUNET_JSON_spec_int16 ("choice_index", 4745 &pc->parse_wallet_data.choice_index), 4746 NULL), 4747 GNUNET_JSON_spec_mark_optional ( 4748 GNUNET_JSON_spec_array_const ("tokens_evs", 4749 &tokens_evs), 4750 NULL), 4751 GNUNET_JSON_spec_mark_optional ( 4752 GNUNET_JSON_spec_object_const ("donau", 4753 &donau_obj), 4754 NULL), 4755 GNUNET_JSON_spec_end () 4756 }; 4757 4758 pc->parse_wallet_data.choice_index = -1; 4759 if (NULL == pc->parse_pay.wallet_data) 4760 { 4761 pc->phase = PP_CHECK_CONTRACT; 4762 return; 4763 } 4764 { 4765 enum GNUNET_GenericReturnValue res; 4766 4767 res = TALER_MHD_parse_json_data (pc->connection, 4768 pc->parse_pay.wallet_data, 4769 spec); 4770 if (GNUNET_YES != res) 4771 { 4772 GNUNET_break_op (0); 4773 pay_end (pc, 4774 (GNUNET_NO == res) 4775 ? MHD_YES 4776 : MHD_NO); 4777 return; 4778 } 4779 } 4780 4781 pc->parse_wallet_data.token_envelopes_cnt 4782 = json_array_size (tokens_evs); 4783 if (pc->parse_wallet_data.token_envelopes_cnt > 4784 MAX_TOKEN_ALLOWED_OUTPUTS) 4785 { 4786 GNUNET_break_op (0); 4787 pay_end (pc, 4788 TALER_MHD_reply_with_error ( 4789 pc->connection, 4790 MHD_HTTP_BAD_REQUEST, 4791 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4792 "'tokens_evs' array too long")); 4793 return; 4794 } 4795 pc->parse_wallet_data.token_envelopes 4796 = GNUNET_new_array (pc->parse_wallet_data.token_envelopes_cnt, 4797 struct TokenEnvelope); 4798 4799 { 4800 unsigned int tokens_ev_index; 4801 json_t *token_ev; 4802 4803 json_array_foreach (tokens_evs, 4804 tokens_ev_index, 4805 token_ev) 4806 { 4807 struct TokenEnvelope *ev 4808 = &pc->parse_wallet_data.token_envelopes[tokens_ev_index]; 4809 struct GNUNET_JSON_Specification ispec[] = { 4810 TALER_JSON_spec_token_envelope (NULL, 4811 &ev->blinded_token), 4812 GNUNET_JSON_spec_end () 4813 }; 4814 enum GNUNET_GenericReturnValue res; 4815 4816 if (json_is_null (token_ev)) 4817 continue; 4818 res = TALER_MHD_parse_json_data (pc->connection, 4819 token_ev, 4820 ispec); 4821 if (GNUNET_YES != res) 4822 { 4823 GNUNET_break_op (0); 4824 pay_end (pc, 4825 (GNUNET_NO == res) 4826 ? MHD_YES 4827 : MHD_NO); 4828 return; 4829 } 4830 4831 for (unsigned int j = 0; j<tokens_ev_index; j++) 4832 { 4833 if (0 == 4834 GNUNET_memcmp (ev->blinded_token.blinded_pub, 4835 pc->parse_wallet_data.token_envelopes[j]. 4836 blinded_token.blinded_pub)) 4837 { 4838 GNUNET_break_op (0); 4839 pay_end (pc, 4840 TALER_MHD_reply_with_error ( 4841 pc->connection, 4842 MHD_HTTP_BAD_REQUEST, 4843 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4844 "duplicate token envelope in list")); 4845 return; 4846 } 4847 } 4848 } 4849 } 4850 4851 if (NULL != donau_obj) 4852 { 4853 const char *donau_url_tmp; 4854 const json_t *budikeypairs; 4855 json_t *donau_keys_json; 4856 4857 /* Fetching and checking that all 3 are present in some way */ 4858 struct GNUNET_JSON_Specification dspec[] = { 4859 GNUNET_JSON_spec_string ("url", 4860 &donau_url_tmp), 4861 GNUNET_JSON_spec_uint64 ("year", 4862 &pc->parse_wallet_data.donau.donation_year), 4863 GNUNET_JSON_spec_array_const ("budikeypairs", 4864 &budikeypairs), 4865 GNUNET_JSON_spec_end () 4866 }; 4867 enum GNUNET_GenericReturnValue res; 4868 4869 res = TALER_MHD_parse_json_data (pc->connection, 4870 donau_obj, 4871 dspec); 4872 if (GNUNET_YES != res) 4873 { 4874 GNUNET_break_op (0); 4875 pay_end (pc, 4876 (GNUNET_NO == res) 4877 ? MHD_YES 4878 : MHD_NO); 4879 return; 4880 } 4881 4882 /* Check if the needed data is present for the given donau URL */ 4883 { 4884 enum GNUNET_DB_QueryStatus qs; 4885 4886 qs = TALER_MERCHANTDB_get_donau_instance_by_url ( 4887 TMH_db, 4888 pc->hc->instance->settings.id, 4889 donau_url_tmp, 4890 &pc->parse_wallet_data.charity_id, 4891 &pc->parse_wallet_data.charity_max_per_year, 4892 &pc->parse_wallet_data.charity_receipts_to_date, 4893 &donau_keys_json, 4894 &pc->parse_wallet_data.donau_instance_serial); 4895 4896 switch (qs) 4897 { 4898 case GNUNET_DB_STATUS_HARD_ERROR: 4899 case GNUNET_DB_STATUS_SOFT_ERROR: 4900 TALER_MERCHANTDB_rollback (TMH_db); 4901 pay_end (pc, 4902 TALER_MHD_reply_with_error ( 4903 pc->connection, 4904 MHD_HTTP_INTERNAL_SERVER_ERROR, 4905 TALER_EC_GENERIC_DB_FETCH_FAILED, 4906 "get_donau_instance_by_url")); 4907 return; 4908 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 4909 TALER_MERCHANTDB_rollback (TMH_db); 4910 pay_end (pc, 4911 TALER_MHD_reply_with_error ( 4912 pc->connection, 4913 MHD_HTTP_NOT_FOUND, 4914 TALER_EC_MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN, 4915 donau_url_tmp)); 4916 return; 4917 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 4918 GNUNET_static_assert (sizeof (pc->parse_wallet_data.charity_priv) == 4919 sizeof (pc->hc->instance->merchant_priv)); 4920 memcpy (&pc->parse_wallet_data.charity_priv, 4921 &pc->hc->instance->merchant_priv, 4922 sizeof (pc->hc->instance->merchant_priv)); 4923 pc->parse_wallet_data.donau.donau_url = 4924 GNUNET_strdup (donau_url_tmp); 4925 break; 4926 } 4927 } 4928 4929 { 4930 pc->parse_wallet_data.donau_keys = 4931 DONAU_keys_from_json (donau_keys_json); 4932 json_decref (donau_keys_json); 4933 if (NULL == pc->parse_wallet_data.donau_keys) 4934 { 4935 GNUNET_break_op (0); 4936 pay_end (pc, 4937 TALER_MHD_reply_with_error (pc->connection, 4938 MHD_HTTP_BAD_REQUEST, 4939 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4940 "Invalid donau_keys")); 4941 return; 4942 } 4943 } 4944 4945 /* Stage to parse the budikeypairs from json to struct */ 4946 if (0 != json_array_size (budikeypairs)) 4947 { 4948 size_t num_bkps = json_array_size (budikeypairs); 4949 struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps = 4950 GNUNET_new_array (num_bkps, 4951 struct DONAU_BlindedUniqueDonorIdentifierKeyPair); 4952 4953 /* Change to json for each */ 4954 for (size_t i = 0; i < num_bkps; i++) 4955 { 4956 const json_t *bkp_obj = json_array_get (budikeypairs, 4957 i); 4958 if (GNUNET_SYSERR == 4959 merchant_parse_json_bkp (&bkps[i], 4960 bkp_obj)) 4961 { 4962 GNUNET_break_op (0); 4963 for (size_t j = 0; j < i; j++) 4964 GNUNET_CRYPTO_blinded_message_decref ( 4965 bkps[j].blinded_udi.blinded_message); 4966 GNUNET_free (bkps); 4967 pay_end (pc, 4968 TALER_MHD_reply_with_error (pc->connection, 4969 MHD_HTTP_BAD_REQUEST, 4970 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4971 "Failed to parse budikeypairs")); 4972 return; 4973 } 4974 } 4975 4976 pc->parse_wallet_data.num_bkps = num_bkps; 4977 pc->parse_wallet_data.bkps = bkps; 4978 } 4979 } 4980 TALER_json_hash (pc->parse_pay.wallet_data, 4981 &pc->parse_wallet_data.h_wallet_data); 4982 4983 pc->phase = PP_CHECK_CONTRACT; 4984 } 4985 4986 4987 /** 4988 * Try to parse the pay request into the given pay context. 4989 * Schedules an error response in the connection on failure. 4990 * 4991 * @param[in,out] pc context we use to handle the payment 4992 */ 4993 static void 4994 phase_parse_pay (struct PayContext *pc) 4995 { 4996 const char *session_id = NULL; 4997 const json_t *coins; 4998 const json_t *tokens; 4999 struct GNUNET_JSON_Specification spec[] = { 5000 GNUNET_JSON_spec_array_const ("coins", 5001 &coins), 5002 GNUNET_JSON_spec_mark_optional ( 5003 GNUNET_JSON_spec_string ("session_id", 5004 &session_id), 5005 NULL), 5006 GNUNET_JSON_spec_mark_optional ( 5007 GNUNET_JSON_spec_object_const ("wallet_data", 5008 &pc->parse_pay.wallet_data), 5009 NULL), 5010 GNUNET_JSON_spec_mark_optional ( 5011 GNUNET_JSON_spec_array_const ("tokens", 5012 &tokens), 5013 NULL), 5014 GNUNET_JSON_spec_end () 5015 }; 5016 5017 #if DEBUG 5018 { 5019 char *dump = json_dumps (pc->hc->request_body, 5020 JSON_INDENT (2) 5021 | JSON_ENCODE_ANY 5022 | JSON_SORT_KEYS); 5023 5024 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5025 "POST /orders/%s/pay – request body follows:\n%s\n", 5026 pc->order_id, 5027 dump); 5028 5029 free (dump); 5030 5031 } 5032 #endif /* DEBUG */ 5033 5034 GNUNET_assert (PP_PARSE_PAY == pc->phase); 5035 { 5036 enum GNUNET_GenericReturnValue res; 5037 5038 res = TALER_MHD_parse_json_data (pc->connection, 5039 pc->hc->request_body, 5040 spec); 5041 if (GNUNET_YES != res) 5042 { 5043 GNUNET_break_op (0); 5044 pay_end (pc, 5045 (GNUNET_NO == res) 5046 ? MHD_YES 5047 : MHD_NO); 5048 return; 5049 } 5050 } 5051 5052 /* copy session ID (if set) */ 5053 if (NULL != session_id) 5054 { 5055 pc->parse_pay.session_id = GNUNET_strdup (session_id); 5056 } 5057 else 5058 { 5059 /* use empty string as default if client didn't specify it */ 5060 pc->parse_pay.session_id = GNUNET_strdup (""); 5061 } 5062 5063 pc->parse_pay.coins_cnt = json_array_size (coins); 5064 if (pc->parse_pay.coins_cnt > MAX_COIN_ALLOWED_COINS) 5065 { 5066 GNUNET_break_op (0); 5067 pay_end (pc, 5068 TALER_MHD_reply_with_error ( 5069 pc->connection, 5070 MHD_HTTP_BAD_REQUEST, 5071 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5072 "'coins' array too long")); 5073 return; 5074 } 5075 /* note: 1 coin = 1 deposit confirmation expected */ 5076 pc->parse_pay.dc = GNUNET_new_array (pc->parse_pay.coins_cnt, 5077 struct DepositConfirmation); 5078 5079 /* This loop populates the array 'dc' in 'pc' */ 5080 { 5081 unsigned int coins_index; 5082 json_t *coin; 5083 5084 json_array_foreach (coins, coins_index, coin) 5085 { 5086 struct DepositConfirmation *dc = &pc->parse_pay.dc[coins_index]; 5087 const char *exchange_url; 5088 struct GNUNET_JSON_Specification ispec[] = { 5089 GNUNET_JSON_spec_fixed_auto ("coin_sig", 5090 &dc->cdd.coin_sig), 5091 GNUNET_JSON_spec_fixed_auto ("coin_pub", 5092 &dc->cdd.coin_pub), 5093 TALER_JSON_spec_denom_sig ("ub_sig", 5094 &dc->cdd.denom_sig), 5095 GNUNET_JSON_spec_fixed_auto ("h_denom", 5096 &dc->cdd.h_denom_pub), 5097 TALER_JSON_spec_amount_any ("contribution", 5098 &dc->cdd.amount), 5099 TALER_JSON_spec_web_url ("exchange_url", 5100 &exchange_url), 5101 /* if a minimum age was required, the minimum_age_sig and 5102 * age_commitment must be provided */ 5103 GNUNET_JSON_spec_mark_optional ( 5104 GNUNET_JSON_spec_fixed_auto ("minimum_age_sig", 5105 &dc->minimum_age_sig), 5106 &dc->no_minimum_age_sig), 5107 GNUNET_JSON_spec_mark_optional ( 5108 TALER_JSON_spec_age_commitment ("age_commitment", 5109 &dc->age_commitment), 5110 &dc->no_age_commitment), 5111 /* if minimum age was not required, but coin with age restriction set 5112 * was used, h_age_commitment must be provided. */ 5113 GNUNET_JSON_spec_mark_optional ( 5114 GNUNET_JSON_spec_fixed_auto ("h_age_commitment", 5115 &dc->cdd.h_age_commitment), 5116 &dc->no_h_age_commitment), 5117 GNUNET_JSON_spec_end () 5118 }; 5119 enum GNUNET_GenericReturnValue res; 5120 struct ExchangeGroup *eg = NULL; 5121 5122 res = TALER_MHD_parse_json_data (pc->connection, 5123 coin, 5124 ispec); 5125 if (GNUNET_YES != res) 5126 { 5127 GNUNET_break_op (0); 5128 pay_end (pc, 5129 (GNUNET_NO == res) 5130 ? MHD_YES 5131 : MHD_NO); 5132 return; 5133 } 5134 for (unsigned int j = 0; j<coins_index; j++) 5135 { 5136 if (0 == 5137 GNUNET_memcmp (&dc->cdd.coin_pub, 5138 &pc->parse_pay.dc[j].cdd.coin_pub)) 5139 { 5140 GNUNET_break_op (0); 5141 pay_end (pc, 5142 TALER_MHD_reply_with_error (pc->connection, 5143 MHD_HTTP_BAD_REQUEST, 5144 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5145 "duplicate coin in list")); 5146 return; 5147 } 5148 } 5149 5150 dc->exchange_url = GNUNET_strdup (exchange_url); 5151 dc->index = coins_index; 5152 dc->pc = pc; 5153 5154 /* Check the consistency of the (potential) age restriction 5155 * information. */ 5156 if (dc->no_age_commitment != dc->no_minimum_age_sig) 5157 { 5158 GNUNET_break_op (0); 5159 pay_end (pc, 5160 TALER_MHD_reply_with_error ( 5161 pc->connection, 5162 MHD_HTTP_BAD_REQUEST, 5163 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5164 "inconsistent: 'age_commitment' vs. 'minimum_age_sig'" 5165 )); 5166 return; 5167 } 5168 5169 /* Setup exchange group */ 5170 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 5171 { 5172 if (0 == 5173 strcmp (pc->parse_pay.egs[i]->exchange_url, 5174 exchange_url)) 5175 { 5176 eg = pc->parse_pay.egs[i]; 5177 break; 5178 } 5179 } 5180 if (NULL == eg) 5181 { 5182 eg = GNUNET_new (struct ExchangeGroup); 5183 eg->pc = pc; 5184 eg->exchange_url = dc->exchange_url; 5185 eg->total = dc->cdd.amount; 5186 GNUNET_array_append (pc->parse_pay.egs, 5187 pc->parse_pay.num_exchanges, 5188 eg); 5189 } 5190 else 5191 { 5192 if (0 > 5193 TALER_amount_add (&eg->total, 5194 &eg->total, 5195 &dc->cdd.amount)) 5196 { 5197 GNUNET_break_op (0); 5198 pay_end (pc, 5199 TALER_MHD_reply_with_error ( 5200 pc->connection, 5201 MHD_HTTP_INTERNAL_SERVER_ERROR, 5202 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 5203 "Overflow adding up amounts")); 5204 return; 5205 } 5206 } 5207 } 5208 } 5209 5210 pc->parse_pay.tokens_cnt = json_array_size (tokens); 5211 if (pc->parse_pay.tokens_cnt > MAX_TOKEN_ALLOWED_INPUTS) 5212 { 5213 GNUNET_break_op (0); 5214 pay_end (pc, 5215 TALER_MHD_reply_with_error ( 5216 pc->connection, 5217 MHD_HTTP_BAD_REQUEST, 5218 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5219 "'tokens' array too long")); 5220 return; 5221 } 5222 5223 pc->parse_pay.tokens = GNUNET_new_array (pc->parse_pay.tokens_cnt, 5224 struct TokenUseConfirmation); 5225 5226 /* This loop populates the array 'tokens' in 'pc' */ 5227 { 5228 unsigned int tokens_index; 5229 json_t *token; 5230 5231 json_array_foreach (tokens, tokens_index, token) 5232 { 5233 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[tokens_index]; 5234 struct GNUNET_JSON_Specification ispec[] = { 5235 GNUNET_JSON_spec_fixed_auto ("token_sig", 5236 &tuc->sig), 5237 GNUNET_JSON_spec_fixed_auto ("token_pub", 5238 &tuc->pub), 5239 GNUNET_JSON_spec_fixed_auto ("h_issue", 5240 &tuc->h_issue), 5241 TALER_JSON_spec_token_issue_sig ("ub_sig", 5242 &tuc->unblinded_sig), 5243 GNUNET_JSON_spec_end () 5244 }; 5245 enum GNUNET_GenericReturnValue res; 5246 5247 res = TALER_MHD_parse_json_data (pc->connection, 5248 token, 5249 ispec); 5250 if (GNUNET_YES != res) 5251 { 5252 GNUNET_break_op (0); 5253 pay_end (pc, 5254 (GNUNET_NO == res) 5255 ? MHD_YES 5256 : MHD_NO); 5257 return; 5258 } 5259 5260 for (unsigned int j = 0; j<tokens_index; j++) 5261 { 5262 if (0 == 5263 GNUNET_memcmp (&tuc->pub, 5264 &pc->parse_pay.tokens[j].pub)) 5265 { 5266 GNUNET_break_op (0); 5267 pay_end (pc, 5268 TALER_MHD_reply_with_error ( 5269 pc->connection, 5270 MHD_HTTP_BAD_REQUEST, 5271 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5272 "duplicate token in list")); 5273 return; 5274 } 5275 } 5276 } 5277 } 5278 5279 pc->phase = PP_PARSE_WALLET_DATA; 5280 } 5281 5282 5283 /** 5284 * Custom cleanup routine for a `struct PayContext`. 5285 * 5286 * @param cls the `struct PayContext` to clean up. 5287 */ 5288 static void 5289 pay_context_cleanup (void *cls) 5290 { 5291 struct PayContext *pc = cls; 5292 5293 if (NULL != pc->batch_deposits.timeout_task) 5294 { 5295 GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task); 5296 pc->batch_deposits.timeout_task = NULL; 5297 } 5298 if (NULL != pc->check_contract.contract_terms_json) 5299 { 5300 json_decref (pc->check_contract.contract_terms_json); 5301 pc->check_contract.contract_terms_json = NULL; 5302 } 5303 for (unsigned int i = 0; i<pc->parse_pay.coins_cnt; i++) 5304 { 5305 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 5306 5307 TALER_denom_sig_free (&dc->cdd.denom_sig); 5308 GNUNET_free (dc->exchange_url); 5309 } 5310 GNUNET_free (pc->parse_pay.dc); 5311 for (unsigned int i = 0; i<pc->parse_pay.tokens_cnt; i++) 5312 { 5313 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 5314 5315 TALER_token_issue_sig_free (&tuc->unblinded_sig); 5316 } 5317 GNUNET_free (pc->parse_pay.tokens); 5318 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 5319 { 5320 struct ExchangeGroup *eg = pc->parse_pay.egs[i]; 5321 5322 if (NULL != eg->fo) 5323 TMH_EXCHANGES_keys4exchange_cancel (eg->fo); 5324 if (NULL != eg->bdh) 5325 TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh); 5326 if (NULL != eg->keys) 5327 TALER_EXCHANGE_keys_decref (eg->keys); 5328 GNUNET_free (eg); 5329 } 5330 GNUNET_free (pc->parse_pay.egs); 5331 if (NULL != pc->check_contract.contract_terms) 5332 { 5333 TALER_MERCHANT_contract_free (pc->check_contract.contract_terms); 5334 pc->check_contract.contract_terms = NULL; 5335 } 5336 if (NULL != pc->response) 5337 { 5338 MHD_destroy_response (pc->response); 5339 pc->response = NULL; 5340 } 5341 GNUNET_free (pc->parse_pay.session_id); 5342 GNUNET_CONTAINER_DLL_remove (pc_head, 5343 pc_tail, 5344 pc); 5345 GNUNET_free (pc->check_contract.pos_key); 5346 GNUNET_free (pc->compute_money_pots.pots); 5347 GNUNET_free (pc->compute_money_pots.increments); 5348 if (NULL != pc->parse_wallet_data.bkps) 5349 { 5350 for (size_t i = 0; i < pc->parse_wallet_data.num_bkps; i++) 5351 GNUNET_CRYPTO_blinded_message_decref ( 5352 pc->parse_wallet_data.bkps[i].blinded_udi.blinded_message); 5353 GNUNET_array_grow (pc->parse_wallet_data.bkps, 5354 pc->parse_wallet_data.num_bkps, 5355 0); 5356 } 5357 if (NULL != pc->parse_wallet_data.donau_keys) 5358 { 5359 DONAU_keys_decref (pc->parse_wallet_data.donau_keys); 5360 pc->parse_wallet_data.donau_keys = NULL; 5361 } 5362 GNUNET_free (pc->parse_wallet_data.donau.donau_url); 5363 for (unsigned int i = 0; i<pc->parse_wallet_data.token_envelopes_cnt; i++) 5364 { 5365 struct TokenEnvelope *ev 5366 = &pc->parse_wallet_data.token_envelopes[i]; 5367 5368 GNUNET_CRYPTO_blinded_message_decref (ev->blinded_token.blinded_pub); 5369 } 5370 GNUNET_free (pc->parse_wallet_data.token_envelopes); 5371 if (NULL != pc->output_tokens) 5372 { 5373 for (unsigned int i = 0; i<pc->output_tokens_len; i++) 5374 if (NULL != pc->output_tokens[i].sig.signature) 5375 GNUNET_CRYPTO_blinded_sig_decref (pc->output_tokens[i].sig.signature); 5376 GNUNET_free (pc->output_tokens); 5377 } 5378 GNUNET_free (pc); 5379 } 5380 5381 5382 enum MHD_Result 5383 TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh, 5384 struct MHD_Connection *connection, 5385 struct TMH_HandlerContext *hc) 5386 { 5387 struct PayContext *pc = hc->ctx; 5388 5389 GNUNET_assert (NULL != hc->infix); 5390 if (NULL == pc) 5391 { 5392 pc = GNUNET_new (struct PayContext); 5393 pc->connection = connection; 5394 pc->hc = hc; 5395 pc->order_id = hc->infix; 5396 hc->ctx = pc; 5397 hc->cc = &pay_context_cleanup; 5398 GNUNET_CONTAINER_DLL_insert (pc_head, 5399 pc_tail, 5400 pc); 5401 } 5402 while (1) 5403 { 5404 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5405 "Processing /pay in phase %d\n", 5406 (int) pc->phase); 5407 switch (pc->phase) 5408 { 5409 case PP_PARSE_PAY: 5410 phase_parse_pay (pc); 5411 break; 5412 case PP_PARSE_WALLET_DATA: 5413 phase_parse_wallet_data (pc); 5414 break; 5415 case PP_CHECK_CONTRACT: 5416 phase_check_contract (pc); 5417 break; 5418 case PP_VALIDATE_TOKENS: 5419 phase_validate_tokens (pc); 5420 break; 5421 case PP_CONTRACT_PAID: 5422 phase_contract_paid (pc); 5423 break; 5424 case PP_COMPUTE_MONEY_POTS: 5425 phase_compute_money_pots (pc); 5426 break; 5427 case PP_PAY_TRANSACTION: 5428 phase_execute_pay_transaction (pc); 5429 break; 5430 case PP_REQUEST_DONATION_RECEIPT: 5431 phase_request_donation_receipt (pc); 5432 break; 5433 case PP_FINAL_OUTPUT_TOKEN_PROCESSING: 5434 phase_final_output_token_processing (pc); 5435 break; 5436 case PP_PAYMENT_NOTIFICATION: 5437 phase_payment_notification (pc); 5438 break; 5439 case PP_SUCCESS_RESPONSE: 5440 phase_success_response (pc); 5441 break; 5442 case PP_BATCH_DEPOSITS: 5443 phase_batch_deposits (pc); 5444 break; 5445 case PP_RETURN_RESPONSE: 5446 phase_return_response (pc); 5447 break; 5448 case PP_FAIL_LEGAL_REASONS: 5449 phase_fail_for_legal_reasons (pc); 5450 break; 5451 case PP_END_YES: 5452 return MHD_YES; 5453 case PP_END_NO: 5454 return MHD_NO; 5455 default: 5456 /* should not be reachable */ 5457 GNUNET_assert (0); 5458 return MHD_NO; 5459 } 5460 switch (pc->suspended) 5461 { 5462 case GNUNET_SYSERR: 5463 /* during shutdown, we don't generate any more replies */ 5464 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5465 "Processing /pay ends due to shutdown in phase %d\n", 5466 (int) pc->phase); 5467 return MHD_NO; 5468 case GNUNET_NO: 5469 /* continue to next phase */ 5470 break; 5471 case GNUNET_YES: 5472 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5473 "Processing /pay suspended in phase %d\n", 5474 (int) pc->phase); 5475 return MHD_YES; 5476 } 5477 } 5478 /* impossible to get here */ 5479 GNUNET_assert (0); 5480 return MHD_YES; 5481 } 5482 5483 5484 /* end of taler-merchant-httpd_post-orders-ORDER_ID-pay.c */