frosix_database_plugin.h (19860B)
1 /* 2 This file is part of Frosix 3 Copyright (C) 2019-2022 Anastasis SARL 4 5 Frosix is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Frosix is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 Frosix; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file include/frosix_database_plugin.h 18 * @brief database access for Frosix 19 * @author Christian Grothoff 20 */ 21 #ifndef FROSIX_DATABASE_PLUGIN_H 22 #define FROSIX_DATABASE_PLUGIN_H 23 24 #include "frosix_service.h" 25 #include "frost_high.h" 26 #include "keygen.h" 27 #include "frosix_util_lib.h" 28 #include <gnunet/gnunet_db_lib.h> 29 #include <taler/taler_util.h> 30 31 /** 32 * How long is an offer for a challenge payment valid for payment? 33 */ 34 #define FROSIX_CHALLENGE_OFFER_LIFETIME GNUNET_TIME_UNIT_HOURS 35 36 /** 37 * FIXME 38 */ 39 enum FROSIX_DB_CommitmentStatus 40 { 41 /** 42 * FIXME 43 */ 44 FROSIX_DB_COMMITMENT_STATUS_HARD_ERROR = -2, 45 46 /** 47 * FIXME 48 */ 49 FROSIX_DB_COMMITMENT_STATUS_SOFT_ERROR = -1, 50 51 /** 52 * FIXME 53 */ 54 FROSIX_DB_COMMITMENT_STATUS_NO_RESULTS = 0, 55 56 /** 57 * FIXME 58 */ 59 FROSIX_DB_COMMITMENT_STATUS_ONE_RESULT = 1, 60 }; 61 62 /** 63 * FIXME 64 */ 65 enum FROSIX_DB_KeyStatus 66 { 67 /** 68 * FIXME 69 */ 70 FROSIX_DB_KEY_STATUS_HARD_ERROR = -2, 71 72 /** 73 * FIXME 74 */ 75 FROSIX_DB_KEY_STATUS_SOFT_ERROR = -1, 76 77 /** 78 * FIXME 79 */ 80 FROSIX_DB_KEY_STATUS_NO_RESULTS = 0, 81 82 /** 83 * FIXME 84 */ 85 FROSIX_DB_KEY_STATUS_ONE_RESULT = 1, 86 }; 87 88 /** 89 * Return values for checking code validity. 90 */ 91 enum FROSIX_DB_CodeStatus 92 { 93 /** 94 * Provided authentication code does not match database content. 95 */ 96 FROSIX_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH = -3, 97 98 /** 99 * Encountered hard error talking to DB. 100 */ 101 FROSIX_DB_CODE_STATUS_HARD_ERROR = -2, 102 103 /** 104 * Encountered serialization error talking to DB. 105 */ 106 FROSIX_DB_CODE_STATUS_SOFT_ERROR = -1, 107 108 /** 109 * We have no challenge in the database. 110 */ 111 FROSIX_DB_CODE_STATUS_NO_RESULTS = 0, 112 113 /** 114 * The provided challenge matches what we have in the database. 115 */ 116 FROSIX_DB_CODE_STATUS_VALID_CODE_STORED = 1, 117 }; 118 119 120 /** 121 * Return values for checking account validity. 122 */ 123 enum FROSIX_DB_AccountStatus 124 { 125 /** 126 * Account is unknown, user should pay to establish it. 127 */ 128 FROSIX_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED = -3, 129 130 /** 131 * Encountered hard error talking to DB. 132 */ 133 FROSIX_DB_ACCOUNT_STATUS_HARD_ERROR = -2, 134 135 /** 136 * Account is valid, but we have no policy stored yet. 137 */ 138 FROSIX_DB_ACCOUNT_STATUS_NO_RESULTS = 0, 139 140 /** 141 * Account is valid, and we have a policy stored. 142 */ 143 FROSIX_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED = 1, 144 }; 145 146 147 /** 148 * Return values for storing data in database with payment. 149 */ 150 enum FROSIX_DB_StoreStatus 151 { 152 /** 153 * The client has stored too many policies, should pay to store more. 154 */ 155 FROSIX_DB_STORE_STATUS_STORE_LIMIT_EXCEEDED = -4, 156 157 /** 158 * The client needs to pay to store policies. 159 */ 160 FROSIX_DB_STORE_STATUS_PAYMENT_REQUIRED = -3, 161 162 /** 163 * Encountered hard error talking to DB. 164 */ 165 FROSIX_DB_STORE_STATUS_HARD_ERROR = -2, 166 167 /** 168 * Despite retrying, we encountered serialization errors. 169 */ 170 FROSIX_DB_STORE_STATUS_SOFT_ERROR = -1, 171 172 /** 173 * Database did not need an update (document exists). 174 */ 175 FROSIX_DB_STORE_STATUS_NO_RESULTS = 0, 176 177 /** 178 * We successfully stored the document. 179 */ 180 FROSIX_DB_STORE_STATUS_SUCCESS = 1, 181 }; 182 183 184 /** 185 * Function called on all pending payments for an account or challenge. 186 * 187 * @param cls closure 188 * @param timestamp for how long have we been waiting 189 * @param payment_secret payment secret / order id in the backend 190 * @param amount how much is the order for 191 */ 192 typedef void 193 (*FROSIX_DB_PaymentPendingIterator)( 194 void *cls, 195 struct GNUNET_TIME_Timestamp timestamp, 196 const struct FROSIX_PaymentSecretP *payment_secret, 197 const struct TALER_Amount *amount); 198 199 200 /** 201 * Function called to test if a given wire transfer 202 * satisfied the authentication requirement of the 203 * IBAN plugin. 204 * 205 * @param cls closure 206 * @param credit amount that was transferred 207 * @param wire_subject subject provided in the wire transfer 208 * @return true if this wire transfer satisfied the authentication check 209 */ 210 typedef bool 211 (*FROSIX_DB_AuthIbanTransfercheck)( 212 void *cls, 213 const struct TALER_Amount *credit, 214 const char *wire_subject); 215 216 217 /** 218 * Function called on matching meta data. Note that if the client did 219 * not provide meta data for @a version, the function will be called 220 * with @a recovery_meta_data being NULL. 221 * 222 * @param cls closure 223 * @param version the version of the recovery document 224 * @param ts timestamp when the document was uploaded 225 * @param recovery_meta_data contains meta data about the encrypted recovery document 226 * @param recovery_meta_data_size size of @a recovery_meta_data blob 227 * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration 228 */ 229 typedef enum GNUNET_GenericReturnValue 230 (*FROSIX_DB_RecoveryMetaCallback)(void *cls, 231 uint32_t version, 232 struct GNUNET_TIME_Timestamp ts, 233 const void *recovery_meta_data, 234 size_t recovery_meta_data_size); 235 236 237 /** 238 * Handle to interact with the database. 239 * 240 * Functions ending with "_TR" run their OWN transaction scope 241 * and MUST NOT be called from within a transaction setup by the 242 * caller. Functions ending with "_NT" require the caller to 243 * setup a transaction scope. Functions without a suffix are 244 * simple, single SQL queries that MAY be used either way. 245 */ 246 struct FROSIX_DatabasePlugin 247 { 248 249 /** 250 * Closure for all callbacks. 251 */ 252 void *cls; 253 254 /** 255 * Name of the library which generated this plugin. Set by the 256 * plugin loader. 257 */ 258 char *library_name; 259 260 /** 261 * Drop anastasis tables. Used for testcases. 262 * 263 * @param cls closure 264 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure 265 */ 266 enum GNUNET_GenericReturnValue 267 (*drop_tables)(void *cls); 268 269 /** 270 * Connect to the database. 271 * 272 * @param cls closure 273 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure 274 */ 275 enum GNUNET_GenericReturnValue 276 (*connect)(void *cls); 277 278 /** 279 * Initialize merchant tables 280 * 281 * @param cls closure 282 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure 283 */ 284 enum GNUNET_GenericReturnValue 285 (*create_tables)(void *cls); 286 287 /** 288 * Function called to perform "garbage collection" on the 289 * database, expiring records we no longer require. Deletes 290 * all user records that are not paid up (and by cascade deletes 291 * the associated recovery documents). Also deletes expired 292 * truth and financial records older than @a fin_expire. 293 * 294 * @param cls closure 295 * @param expire_backups backups older than the given time stamp should be garbage collected 296 * @param expire_pending_payments payments still pending from since before 297 * this value should be garbage collected 298 * @return transaction status 299 */ 300 enum GNUNET_DB_QueryStatus 301 (*gc)(void *cls, 302 struct GNUNET_TIME_Absolute expire, 303 struct GNUNET_TIME_Absolute expire_pending_payments); 304 305 /** 306 * Do a pre-flight check that we are not in an uncommitted transaction. 307 * If we are, try to commit the previous transaction and output a warning. 308 * Does not return anything, as we will continue regardless of the outcome. 309 * 310 * @param cls the `struct PostgresClosure` with the plugin-specific state 311 * @return #GNUNET_OK if everything is fine 312 * #GNUNET_NO if a transaction was rolled back 313 * #GNUNET_SYSERR on hard errors 314 */ 315 enum GNUNET_GenericReturnValue 316 (*preflight)(void *cls); 317 318 /** 319 * Check that the database connection is still up. 320 * 321 * @param pg connection to check 322 */ 323 void 324 (*check_connection) (void *cls); 325 326 /** 327 * Roll back the current transaction of a database connection. 328 * 329 * @param cls the `struct PostgresClosure` with the plugin-specific state 330 * @return #GNUNET_OK on success 331 */ 332 void 333 (*rollback) (void *cls); 334 335 /** 336 * Start a transaction. 337 * 338 * @param cls the `struct PostgresClosure` with the plugin-specific state 339 * @param name unique name identifying the transaction (for debugging), 340 * must point to a constant 341 * @return #GNUNET_OK on success 342 */ 343 int 344 (*start) (void *cls, 345 const char *name); 346 347 /** 348 * Commit the current transaction of a database connection. 349 * 350 * @param cls the `struct PostgresClosure` with the plugin-specific state 351 * @return transaction status code 352 */ 353 enum GNUNET_DB_QueryStatus 354 (*commit)(void *cls); 355 356 357 /** 358 * Register callback to be invoked on events of type @a es. 359 * 360 * @param cls database context to use 361 * @param es specification of the event to listen for 362 * @param timeout how long to wait for the event 363 * @param cb function to call when the event happens, possibly 364 * multiple times (until cancel is invoked) 365 * @param cb_cls closure for @a cb 366 * @return handle useful to cancel the listener 367 */ 368 struct GNUNET_DB_EventHandler * 369 (*event_listen)(void *cls, 370 const struct GNUNET_DB_EventHeaderP *es, 371 struct GNUNET_TIME_Relative timeout, 372 GNUNET_DB_EventCallback cb, 373 void *cb_cls); 374 375 /** 376 * Stop notifications. 377 * 378 * @param eh handle to unregister. 379 */ 380 void 381 (*event_listen_cancel)(struct GNUNET_DB_EventHandler *eh); 382 383 384 /** 385 * Notify all that listen on @a es of an event. 386 * 387 * @param cls database context to use 388 * @param es specification of the event to generate 389 * @param extra additional event data provided 390 * @param extra_size number of bytes in @a extra 391 */ 392 void 393 (*event_notify)(void *cls, 394 const struct GNUNET_DB_EventHeaderP *es, 395 const void *extra, 396 size_t extra_size); 397 398 399 /** 400 * FIXME 401 */ 402 enum FROSIX_DB_StoreStatus 403 (*store_dkg_commitment)( 404 void *cls, 405 const struct FROSIX_DkgRequestIdP *dkg_id, 406 const struct FROSIX_DkgCommitmentsRaw *dkg_commits); 407 408 /** 409 * FIXME 410 */ 411 enum GNUNET_DB_QueryStatus 412 (*get_dkg_commitment)( 413 void *cls, 414 const struct FROSIX_DkgRequestIdP *dkg_id, 415 struct FROSIX_DkgCommitmentsRaw *dkg_commits); 416 417 418 /** 419 * FIXME 420 */ 421 enum FROSIX_DB_CommitmentStatus 422 (*lookup_dkg_commitment)( 423 void *cls, 424 const struct FROSIX_DkgRequestIdP *dkg_id); 425 426 427 /** 428 * FIXME 429 */ 430 enum FROSIX_DB_StoreStatus 431 (*store_key)( 432 void *cls, 433 const struct FROST_HashCode *id, 434 const struct FROSIX_EncryptionNonceP *nonce, 435 const struct FROSIX_KeyDataEncrypted *key_data, 436 const struct FROSIX_ChallengeHashP *challenge_hash, 437 uint32_t expiration, 438 uint8_t identifier); 439 440 /** 441 * FIXME 442 */ 443 enum FROSIX_DB_KeyStatus 444 (*lookup_key)( 445 void *cls, 446 const struct FROST_HashCode *id); 447 448 449 /** 450 * FIXME 451 */ 452 enum GNUNET_DB_QueryStatus 453 (*get_auth_hash)( 454 void *cls, 455 const struct FROST_HashCode *db_id, 456 struct FROSIX_ChallengeHashP *challenge_hash); 457 458 459 /** 460 * FIXME 461 */ 462 enum GNUNET_DB_QueryStatus 463 (*get_key_data)( 464 void *cls, 465 const struct FROST_HashCode *db_id, 466 uint32_t *identifier, 467 struct FROSIX_EncryptionNonceP *nonce, 468 struct FROSIX_KeyDataEncrypted *enc_key_data); 469 470 471 /** 472 * FIXME 473 */ 474 enum GNUNET_DB_QueryStatus 475 (*delete_key_data)( 476 void *cls, 477 const struct FROST_HashCode *db_id); 478 479 480 /** 481 * FIXME 482 */ 483 enum GNUNET_DB_QueryStatus 484 (*store_commitment_seed)( 485 void *cls, 486 const struct GNUNET_HashCode *db_id, 487 const struct FROST_CommitmentSeed *seed); 488 489 490 /** 491 * FIXME 492 */ 493 enum GNUNET_DB_QueryStatus 494 (*get_and_delete_commitment_seed)( 495 void *cls, 496 const struct GNUNET_HashCode *db_id, 497 struct FROST_CommitmentSeed *seed); 498 499 500 /** 501 * Verify the provided code with the code on the server. 502 * If the code matches the function will return with success, if the code 503 * does not match, the retry counter will be decreased by one. 504 * 505 * @param cls closure 506 * @param truth_uuid identification of the challenge which the code corresponds to 507 * @param hashed_code code which the user provided and wants to verify 508 * @param[out] code set to the original numeric code 509 * @param[out] satisfied set to true if the challenge is set to satisfied 510 * @return transaction status 511 */ 512 enum FROSIX_DB_CodeStatus 513 (*verify_challenge_code)( 514 void *cls, 515 const struct FROSIX_ChallengeIdP *truth_uuid, 516 const struct GNUNET_HashCode *hashed_code, 517 uint64_t *code, 518 bool *satisfied); 519 520 521 /** 522 * Set the 'satisfied' bit for the given challenge and code to 523 * 'true'. 524 * 525 * @param cls closure 526 * @param truth_uuid identification of the challenge which the code corresponds to 527 * @param code code which is now satisfied 528 * @return transaction status 529 */ 530 enum GNUNET_DB_QueryStatus 531 (*mark_challenge_code_satisfied)( 532 void *cls, 533 const struct FROSIX_ChallengeIdP *truth_uuid, 534 uint64_t code); 535 536 537 /** 538 * Check if the 'satisfied' bit for the given challenge and code is 539 * 'true' and the challenge code is not yet expired. 540 * 541 * @param cls closure 542 * @param truth_uuid identification of the challenge which the code corresponds to 543 * @param code code which is now satisfied 544 * @param after after what time must the challenge have been created 545 * @return transaction status, 546 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the challenge code is not satisfied or expired 547 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the challenge code has been marked as satisfied 548 */ 549 enum GNUNET_DB_QueryStatus 550 (*test_challenge_code_satisfied)( 551 void *cls, 552 const struct FROSIX_ChallengeIdP *truth_uuid, 553 const uint64_t code, 554 struct GNUNET_TIME_Timestamp after); 555 556 557 /** 558 * Insert a new challenge code for a given challenge identified by the challenge 559 * public key. The function will first check if there is already a valid code 560 * for this challenge present and won't insert a new one in this case. 561 * 562 * @param cls closure 563 * @param truth_uuid the identifier for the challenge 564 * @param rotation_period for how long is the code available 565 * @param validity_period for how long is the code available 566 * @param retry_counter amount of retries allowed 567 * @param[out] retransmission_date when to next retransmit 568 * @param[out] code set to the code which will be checked for later 569 * @return transaction status, 570 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we are out of valid tries, 571 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a code is now in the DB 572 */ 573 enum GNUNET_DB_QueryStatus 574 (*create_challenge_code)( 575 void *cls, 576 const struct FROSIX_ChallengeIdP *truth_uuid, 577 struct GNUNET_TIME_Relative rotation_period, 578 struct GNUNET_TIME_Relative validity_period, 579 uint32_t retry_counter, 580 struct GNUNET_TIME_Timestamp *retransmission_date, 581 uint64_t *code); 582 583 584 /** 585 * Remember in the database that we successfully sent a challenge. 586 * 587 * @param cls closure 588 * @param truth_uuid the identifier for the challenge 589 * @param code the challenge that was sent 590 */ 591 enum GNUNET_DB_QueryStatus 592 (*mark_challenge_sent)( 593 void *cls, 594 const struct FROSIX_ChallengeIdP *truth_uuid, 595 uint64_t code); 596 597 598 /** 599 * Store payment for challenge. 600 * 601 * @param cls closure 602 * @param truth_key identifier of the challenge to pay 603 * @param payment_secret payment secret which the user must provide with every upload 604 * @param amount how much we asked for 605 * @return transaction status 606 */ 607 enum GNUNET_DB_QueryStatus 608 (*record_challenge_payment)( 609 void *cls, 610 const struct FROSIX_ChallengeIdP *truth_uuid, 611 const struct FROSIX_PaymentSecretP *payment_secret, 612 const struct TALER_Amount *amount); 613 614 615 /** 616 * Record refund for challenge. 617 * 618 * @param cls closure 619 * @param truth_uuid identifier of the challenge to refund 620 * @param payment_secret payment secret which the user must provide with every upload 621 * @return transaction status 622 */ 623 enum GNUNET_DB_QueryStatus 624 (*record_challenge_refund)( 625 void *cls, 626 const struct FROSIX_ChallengeIdP *truth_uuid, 627 const struct FROSIX_PaymentSecretP *payment_secret); 628 629 630 /** 631 * Lookup for a pending payment for a certain challenge 632 * 633 * @param cls closure 634 * @param truth_uuid identification of the challenge 635 * @param[out] payment_secret set to the challenge payment secret 636 * @return transaction status 637 */ 638 enum GNUNET_DB_QueryStatus 639 (*lookup_challenge_payment)( 640 void *cls, 641 const struct FROSIX_ChallengeIdP *truth_uuid, 642 struct FROSIX_PaymentSecretP *payment_secret); 643 644 645 /** 646 * Update payment status of challenge 647 * 648 * @param cls closure 649 * @param truth_uuid which challenge received a payment 650 * @param payment_identifier proof of payment, must be unique and match pending payment 651 * @return transaction status 652 */ 653 enum GNUNET_DB_QueryStatus 654 (*update_challenge_payment)( 655 void *cls, 656 const struct FROSIX_ChallengeIdP *truth_uuid, 657 const struct FROSIX_PaymentSecretP *payment_identifier); 658 659 660 /** 661 * Store inbound IBAN payment made for authentication. 662 * 663 * @param cls closure 664 * @param wire_reference unique identifier inside LibEuFin/Nexus 665 * @param wire_subject subject of the wire transfer 666 * @param amount how much was transferred 667 * @param debit_account account that was debited 668 * @param credit_account Anastasis operator account credited 669 * @param execution_date when was the transfer made 670 * @return transaction status 671 */ 672 enum GNUNET_DB_QueryStatus 673 (*record_auth_iban_payment)( 674 void *cls, 675 uint8_t wire_reference, 676 const char *wire_subject, 677 const struct TALER_Amount *amount, 678 const char *debit_account, 679 const char *credit_account, 680 struct GNUNET_TIME_Timestamp execution_date); 681 682 683 /** 684 * Function to check if we are aware of a wire transfer 685 * that satisfies the IBAN plugin's authentication check. 686 * 687 * @param cls closure 688 * @param debit_account which debit account to check 689 * @param earliest_date earliest date to check 690 * @param cb function to call on all entries found 691 * @param cb_cls closure for @a cb 692 * @return transaction status, 693 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb 694 * returned 'true' once 695 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no 696 * wire transfers existed for which @a cb returned true 697 */ 698 enum GNUNET_DB_QueryStatus 699 (*test_auth_iban_payment)( 700 void *cls, 701 const char *debit_account, 702 struct GNUNET_TIME_Timestamp earliest_date, 703 FROSIX_DB_AuthIbanTransfercheck cb, 704 void *cb_cls); 705 706 707 /** 708 * Function to check the last known IBAN payment. 709 * 710 * @param cls closure 711 * @param credit_account which credit account to check 712 * @param[out] last_row set to the last known row 713 * @return transaction status, 714 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb 715 * returned 'true' once 716 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no 717 * wire transfers existed for which @a cb returned true 718 */ 719 enum GNUNET_DB_QueryStatus 720 (*get_last_auth_iban_payment_row)( 721 void *cls, 722 const char *credit_account, 723 uint8_t *last_row); 724 725 726 /** 727 * Function called to remove all expired codes from the database. 728 * 729 * @return transaction status 730 */ 731 enum GNUNET_DB_QueryStatus 732 (*challenge_gc)(void *cls); 733 734 735 }; 736 #endif