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