diff options
Diffstat (limited to 'src/include/taler_exchangedb_plugin.h')
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 2249 |
1 files changed, 1862 insertions, 387 deletions
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index ab6158a54..2d5857677 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,6 +18,7 @@ * @brief Low-level (statement-level) database access for the exchange * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H @@ -26,6 +27,74 @@ #include <gnunet/gnunet_db_lib.h> #include "taler_json_lib.h" #include "taler_signatures.h" +#include "taler_extensions_policy.h" + +/** + * The conflict that can occur for the age restriction + */ +enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict +{ + /** + * Value OK, no conflict + */ + TALER_AgeCommitmentHash_NoConflict = 0, + + /** + * Given hash had a value, but NULL (or zero) was expected + */ + TALER_AgeCommitmentHash_NullExpected = 1, + + /** + * Given hash was NULL, but value was expected + */ + TALER_AgeCommitmentHash_ValueExpected = 2, + + /** + * Given hash differs from value in the known coin + */ + TALER_AgeCommitmentHash_ValueDiffers = 3, +}; + +/** + * Per-coin information returned when doing a batch insert. + */ +struct TALER_EXCHANGEDB_CoinInfo +{ + /** + * Row of the coin in the known_coins table. + */ + uint64_t known_coin_id; + + /** + * Hash of the denomination, relevant on @e denom_conflict. + */ + struct TALER_DenominationHashP denom_hash; + + /** + * Hash of the age commitment, relevant on @e age_conflict. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * True if the coin was known previously. + */ + bool existed; + + /** + * True if the known coin has a different denomination; + * application will find denomination of the already + * known coin in @e denom_hash. + */ + bool denom_conflict; + + /** + * Indicates if and what kind of conflict with the age + * restriction of the known coin was present; + * application will find age commitment of the already + * known coin in @e h_age_commitment. + */ + enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict age_conflict; +}; /** @@ -106,7 +175,25 @@ struct TALER_EXCHANGEDB_DenominationKeyInformation GNUNET_NETWORK_STRUCT_BEGIN /** - * Signature of events signalling a reserve got funding. + * Events signalling that a coin deposit status + * changed. + */ +struct TALER_CoinDepositEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_DEPOSIT_STATUS_CHANGED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the merchant. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + +}; + +/** + * Events signalling a reserve got funding. */ struct TALER_ReserveEventP { @@ -192,12 +279,17 @@ struct TALER_EXCHANGEDB_SignkeyMetaData */ enum TALER_EXCHANGEDB_ReplicatedTable { + /* From exchange-0002.sql: */ TALER_EXCHANGEDB_RT_DENOMINATIONS, TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS, TALER_EXCHANGEDB_RT_WIRE_TARGETS, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_REQUIREMENTS, TALER_EXCHANGEDB_RT_RESERVES, TALER_EXCHANGEDB_RT_RESERVES_IN, TALER_EXCHANGEDB_RT_RESERVES_CLOSE, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS, TALER_EXCHANGEDB_RT_RESERVES_OUT, TALER_EXCHANGEDB_RT_AUDITORS, TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS, @@ -207,7 +299,8 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_REFRESH_COMMITMENTS, TALER_EXCHANGEDB_RT_REFRESH_REVEALED_COINS, TALER_EXCHANGEDB_RT_REFRESH_TRANSFER_KEYS, - TALER_EXCHANGEDB_RT_DEPOSITS, + TALER_EXCHANGEDB_RT_BATCH_DEPOSITS, + TALER_EXCHANGEDB_RT_COIN_DEPOSITS, TALER_EXCHANGEDB_RT_REFUNDS, TALER_EXCHANGEDB_RT_WIRE_OUT, TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING, @@ -216,9 +309,10 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_RECOUP, TALER_EXCHANGEDB_RT_RECOUP_REFRESH, TALER_EXCHANGEDB_RT_EXTENSIONS, - TALER_EXCHANGEDB_RT_EXTENSION_DETAILS, + TALER_EXCHANGEDB_RT_POLICY_DETAILS, + TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS, TALER_EXCHANGEDB_RT_PURSE_REQUESTS, - TALER_EXCHANGEDB_RT_PURSE_REFUNDS, + TALER_EXCHANGEDB_RT_PURSE_DECISION, TALER_EXCHANGEDB_RT_PURSE_MERGES, TALER_EXCHANGEDB_RT_PURSE_DEPOSITS, TALER_EXCHANGEDB_RT_ACCOUNT_MERGES, @@ -229,6 +323,12 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_WADS_IN, TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES, TALER_EXCHANGEDB_RT_PROFIT_DRAINS, + /* From exchange-0003.sql: */ + TALER_EXCHANGEDB_RT_AML_STAFF, + TALER_EXCHANGEDB_RT_AML_HISTORY, + TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, + TALER_EXCHANGEDB_RT_PURSE_DELETION, + TALER_EXCHANGEDB_RT_AGE_WITHDRAW, }; @@ -283,6 +383,23 @@ struct TALER_EXCHANGEDB_TableData struct { + struct TALER_PaytoHashP h_payto; + struct GNUNET_TIME_Timestamp expiration_time; + char *provider_section; + char *provider_user_id; + char *provider_legitimization_id; + } legitimization_processes; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_ReservePublicKeyP reserve_pub; + bool no_reserve_pub; + char *required_checks; + } legitimization_requirements; + + struct + { struct TALER_ReservePublicKeyP reserve_pub; struct GNUNET_TIME_Timestamp expiration_date; struct GNUNET_TIME_Timestamp gc_date; @@ -301,6 +418,25 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp request_timestamp; + struct GNUNET_TIME_Timestamp expiration_date; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount reserve_payment; + uint32_t requested_purse_limit; + } reserves_open_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount contribution; + } reserves_open_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; struct GNUNET_TIME_Timestamp execution_date; struct TALER_WireTransferIdentifierRawP wtid; struct TALER_PaytoHashP sender_account_h_payto; @@ -388,26 +524,33 @@ struct TALER_EXCHANGEDB_TableData struct { uint64_t shard; - uint64_t known_coin_id; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_Amount amount_with_fee; + struct TALER_MerchantPublicKeyP merchant_pub; struct GNUNET_TIME_Timestamp wallet_timestamp; struct GNUNET_TIME_Timestamp exchange_timestamp; struct GNUNET_TIME_Timestamp refund_deadline; struct GNUNET_TIME_Timestamp wire_deadline; - struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_PrivateContractHashP h_contract_terms; - struct TALER_CoinSpendSignatureP coin_sig; + struct GNUNET_HashCode wallet_data_hash; + bool no_wallet_data_hash; struct TALER_WireSaltP wire_salt; struct TALER_PaytoHashP wire_target_h_payto; - bool extension_blocked; - uint64_t extension_details_serial_id; - } deposits; + bool policy_blocked; + uint64_t policy_details_serial_id; + bool no_policy_details; + } batch_deposits; struct { + uint64_t batch_deposit_serial_id; struct TALER_CoinSpendPublicKeyP coin_pub; - uint64_t deposit_serial_id; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_Amount amount_with_fee; + } coin_deposits; + + struct + { + struct TALER_CoinSpendPublicKeyP coin_pub; + uint64_t batch_deposit_serial_id; struct TALER_MerchantSignatureP merchant_sig; uint64_t rtransaction_id; struct TALER_Amount amount_with_fee; @@ -424,7 +567,7 @@ struct TALER_EXCHANGEDB_TableData struct { - uint64_t deposit_serial_id; + uint64_t batch_deposit_serial_id; struct TALER_WireTransferIdentifierRawP wtid_raw; } aggregation_tracking; @@ -443,7 +586,6 @@ struct TALER_EXCHANGEDB_TableData struct GNUNET_TIME_Timestamp end_date; struct TALER_GlobalFeeSet fees; struct GNUNET_TIME_Relative purse_timeout; - struct GNUNET_TIME_Relative kyc_timeout; struct GNUNET_TIME_Relative history_expiration; uint32_t purse_account_limit; struct TALER_MasterSignatureP master_sig; @@ -453,7 +595,7 @@ struct TALER_EXCHANGEDB_TableData { struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; struct TALER_Amount amount; struct GNUNET_TIME_Timestamp timestamp; uint64_t reserve_out_serial_id; @@ -464,7 +606,7 @@ struct TALER_EXCHANGEDB_TableData uint64_t known_coin_id; struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; struct TALER_Amount amount; struct GNUNET_TIME_Timestamp timestamp; uint64_t rrc_serial; @@ -473,13 +615,32 @@ struct TALER_EXCHANGEDB_TableData struct { char *name; - char *config; + char *manifest; } extensions; struct { - char *extension_options; - } extension_details; + struct GNUNET_HashCode hash_code; + json_t *policy_json; + bool no_policy_json; + struct GNUNET_TIME_Timestamp deadline; + struct TALER_Amount commitment; + struct TALER_Amount accumulated_total; + struct TALER_Amount fee; + struct TALER_Amount transferable; + uint16_t fulfillment_state; /* will also be recomputed */ + uint64_t fulfillment_id; + bool no_fulfillment_id; + } policy_details; + + struct + { + struct GNUNET_TIME_Timestamp fulfillment_timestamp; + char *fulfillment_proof; + struct GNUNET_HashCode h_fulfillment_proof; + struct GNUNET_HashCode *policy_hash_codes; + size_t policy_hash_codes_count; + } policy_fulfillments; struct { @@ -498,7 +659,9 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_PurseContractPublicKeyP purse_pub; - } purse_refunds; + struct GNUNET_TIME_Timestamp action_timestamp; + bool refunded; + } purse_decision; struct { @@ -523,6 +686,7 @@ struct TALER_EXCHANGEDB_TableData struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReserveSignatureP reserve_sig; struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PaytoHashP wallet_h_payto; } account_merges; struct @@ -539,6 +703,8 @@ struct TALER_EXCHANGEDB_TableData struct GNUNET_TIME_Timestamp close_timestamp; struct TALER_ReserveSignatureP reserve_sig; struct TALER_Amount close; + struct TALER_Amount close_fee; + char *payto_uri; } close_requests; struct @@ -597,6 +763,60 @@ struct TALER_EXCHANGEDB_TableData struct TALER_MasterSignatureP master_sig; } profit_drains; + struct + { + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_MasterSignatureP master_sig; + char *decider_name; + bool is_active; + bool read_only; + struct GNUNET_TIME_Timestamp last_change; + } aml_staff; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_Amount new_threshold; + enum TALER_AmlDecisionState new_status; + struct GNUNET_TIME_Timestamp decision_time; + char *justification; + char *kyc_requirements; /* NULL allowed! */ + uint64_t kyc_req_row; + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_AmlOfficerSignatureP decider_sig; + } aml_history; + + struct + { + struct TALER_PaytoHashP h_payto; + struct GNUNET_ShortHashCode kyc_prox; + char *provider; + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + void *encrypted_attributes; + size_t encrypted_attributes_size; + } kyc_attributes; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseContractSignatureP purse_sig; + } purse_deletion; + + struct + { + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + struct TALER_Amount amount_with_fee; + uint16_t max_age; + uint32_t noreveal_index; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint64_t num_coins; + uint64_t *denominations_serials; + void *h_blind_evs; + struct TALER_BlindedDenominationSignature denom_sigs; + } age_withdraw; + } details; }; @@ -756,6 +976,13 @@ struct TALER_EXCHANGEDB_Reserve struct TALER_EXCHANGEDB_DenominationKeyMetaData { /** + * Serial of the denomination key as in the DB. + * Can be used in calls to stored procedures in order to spare + * additional lookups. + */ + uint64_t serial; + + /** * Start time of the validity period for this key. */ struct GNUNET_TIME_Timestamp start; @@ -878,6 +1105,25 @@ typedef void /** + * Function called on all legitimization operations + * we have performed for the given account so far + * (and that have not yet expired). + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + * @param provider_user_id UID at a provider (can be NULL) + * @param legi_id legitimization process ID (can be NULL) + */ +typedef void +(*TALER_EXCHANGEDB_LegitimizationProcessCallback)( + void *cls, + const char *kyc_provider_section_name, + const char *provider_user_id, + const char *legi_id); + + +/** * Function called with information about the exchange's auditors. * * @param cls closure with a `struct TEH_KeyStateHandle *` @@ -970,6 +1216,79 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin /** + * @brief Information we keep for an age-withdraw request + * to reproduce the /age-withdraw operation if needed, and to have proof + * that a reserve was drained by this amount. + */ +struct TALER_EXCHANGEDB_AgeWithdraw +{ + /** + * Total amount (with fee) committed to withdraw + */ + struct TALER_Amount amount_with_fee; + + /** + * Maximum age (in years) that the coins are restricted to. + */ + uint16_t max_age; + + /** + * The hash of the commitment of all n*kappa coins + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not have + * revealed during cut and choose. This value applies to all n coins in the + * commitment. + */ + uint16_t noreveal_index; + + /** + * Public key of the reserve that was drained. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Signature confirming the age withdrawal commitment, matching @e + * reserve_pub, @e max_age and @e h_commitment and @e amount_with_fee. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Number of coins to be withdrawn. + */ + size_t num_coins; + + /** + * Array of @a num_coins blinded coins. These are the chosen coins + * (according to @a noreveal_index) from the request, which contained + * kappa*num_coins blinded coins. + */ + struct TALER_BlindedCoinHashP *h_coin_evs; + + /** + * Array of @a num_coins denomination signatures of the blinded coins @a + * h_coin_evs. + */ + struct TALER_BlindedDenominationSignature *denom_sigs; + + /** + * Array of @a num_coins serial id's of the denominations, corresponding to + * the coins in @a h_coin_evs. + */ + uint64_t *denom_serials; + + /** + * [out]-Array of @a num_coins hashes of the public keys of the denominations + * identified by @e denom_serials. This field is set when calling + * get_age_withdraw + */ + struct TALER_DenominationHashP *denom_pub_hashes; +}; + + +/** * Information the exchange records about a recoup request * in a reserve history. */ @@ -985,7 +1304,7 @@ struct TALER_EXCHANGEDB_Recoup * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -1039,7 +1358,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -1087,7 +1406,7 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry * Blinding factor supplied to prove to the exchange that * the coin came from this @e old_coin_pub. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -1211,6 +1530,76 @@ struct TALER_EXCHANGEDB_HistoryRequest /** + * Details about a (paid for) reserve open request. + */ +struct TALER_EXCHANGEDB_OpenRequest +{ + /** + * Public key of the reserve the open request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request from the reserve. + */ + struct TALER_Amount open_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * How long was the reserve supposed to be open. + */ + struct GNUNET_TIME_Timestamp reserve_expiration; + + /** + * Signature by the reserve approving the open request, + * with purpose #TALER_SIGNATURE_WALLET_RESERVE_OPEN. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * How many open purses should be included with the + * open reserve? + */ + uint32_t purse_limit; + +}; + + +/** + * Details about an (explicit) reserve close request. + */ +struct TALER_EXCHANGEDB_CloseRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; + +}; + + +/** * @brief Types of operations on a reserve. */ enum TALER_EXCHANGEDB_ReserveOperation @@ -1246,7 +1635,17 @@ enum TALER_EXCHANGEDB_ReserveOperation /** * Event where a wallet paid for a full reserve history. */ - TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5 + TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5, + + /** + * Event where a wallet paid to open a reserve for longer. + */ + TALER_EXCHANGEDB_RO_OPEN_REQUEST = 6, + + /** + * Event where a wallet requested a reserve to be closed. + */ + TALER_EXCHANGEDB_RO_CLOSE_REQUEST = 7 }; @@ -1307,12 +1706,146 @@ struct TALER_EXCHANGEDB_ReserveHistory */ struct TALER_EXCHANGEDB_HistoryRequest *history; + /** + * Details about a (paid for) open reserve request. + */ + struct TALER_EXCHANGEDB_OpenRequest *open_request; + + /** + * Details about an (explicit) reserve close request. + */ + struct TALER_EXCHANGEDB_CloseRequest *close_request; + } details; }; /** + * @brief Data about a coin for a deposit operation. + */ +struct TALER_EXCHANGEDB_CoinDepositInformation +{ + /** + * Information about the coin that is being deposited. + */ + struct TALER_CoinPublicInfo coin; + + /** + * ECDSA signature affirming that the customer intends + * this coin to be deposited at the merchant identified + * by @e h_wire in relation to the proposal data identified + * by @e h_contract_terms. + */ + struct TALER_CoinSpendSignatureP csig; + + /** + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount_with_fee; + +}; + + +/** + * @brief Data from a batch deposit operation. + */ +struct TALER_EXCHANGEDB_BatchDeposit +{ + + /** + * Public key of the merchant. Enables later identification + * of the merchant in case of a need to rollback transactions. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Hash over the proposal data between merchant and customer + * (remains unknown to the Exchange). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Hash over additional inputs by the wallet. + */ + struct GNUNET_HashCode wallet_data_hash; + + /** + * Unsalted hash over @e receiver_wire_account. + */ + struct TALER_PaytoHashP wire_target_h_payto; + + /** + * Salt used by the merchant to compute "h_wire". + */ + struct TALER_WireSaltP wire_salt; + + /** + * Time when this request was generated. Used, for example, to + * assess when (roughly) the income was achieved for tax purposes. + * Note that the Exchange will only check that the timestamp is not "too + * far" into the future (i.e. several days). The fact that the + * timestamp falls within the validity period of the coin's + * denomination key is irrelevant for the validity of the deposit + * request, as obviously the customer and merchant could conspire to + * set any timestamp. Also, the Exchange must accept very old deposit + * requests, as the merchant might have been unable to transmit the + * deposit request in a timely fashion (so back-dating is not + * prevented). + */ + struct GNUNET_TIME_Timestamp wallet_timestamp; + + /** + * How much time does the merchant have to issue a refund request? + * Zero if refunds are not allowed. After this time, the coin + * cannot be refunded. + */ + struct GNUNET_TIME_Timestamp refund_deadline; + + /** + * How much time does the merchant have to execute the wire transfer? + * This time is advisory for aggregating transactions, not a hard + * constraint (as the merchant can theoretically pick any time, + * including one in the past). + */ + struct GNUNET_TIME_Timestamp wire_deadline; + + /** + * Row ID of the policy details; 0 if no policy applies. + */ + uint64_t policy_details_serial_id; + + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + const char *receiver_wire_account; + + /** + * Array about the coins that are being deposited. + */ + const struct TALER_EXCHANGEDB_CoinDepositInformation *cdis; + + /** + * Length of the @e cdis array. + */ + unsigned int num_cdis; + + /** + * False if @e wallet_data_hash was provided + */ + bool no_wallet_data_hash; + + /** + * True if further processing is blocked by policy. + */ + bool policy_blocked; + +}; + + +/** * @brief Data from a deposit operation. The combination of * the coin's public key, the merchant's public key and the * transaction ID must be unique. While a coin can (theoretically) be @@ -1355,16 +1888,15 @@ struct TALER_EXCHANGEDB_Deposit struct TALER_WireSaltP wire_salt; /** - * Information about the receiver for executing the transaction. URI in - * payto://-format. + * Hash over inputs from the wallet to customize the contract. */ - char *receiver_wire_account; + struct GNUNET_HashCode wallet_data_hash; /** - * Additional details for extensions relevant for this - * deposit operation, possibly NULL! + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature */ - json_t *extension_details; + struct TALER_ExtensionPolicyHashP h_policy; /** * Time when this request was generated. Used, for example, to @@ -1407,6 +1939,22 @@ struct TALER_EXCHANGEDB_Deposit */ struct TALER_Amount deposit_fee; + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + char *receiver_wire_account; + + /** + * True if @e policy_json was provided + */ + bool has_policy; + + /** + * True if @e wallet_data_hash is not in use. + */ + bool no_wallet_data_hash; + }; @@ -1438,6 +1986,11 @@ struct TALER_EXCHANGEDB_DepositListEntry struct TALER_PrivateContractHashP h_contract_terms; /** + * Hash over inputs from the wallet to customize the contract. + */ + struct GNUNET_HashCode wallet_data_hash; + + /** * Hash of the public denomination key used to sign the coin. */ struct TALER_DenominationHashP h_denom_pub; @@ -1449,20 +2002,26 @@ struct TALER_EXCHANGEDB_DepositListEntry struct TALER_AgeCommitmentHash h_age_commitment; /** - * true, if age commitment is not applicable + * Salt used to compute h_wire from the @e receiver_wire_account. */ - bool no_age_commitment; + struct TALER_WireSaltP wire_salt; /** - * Detailed information about the receiver for executing the transaction. - * URL in payto://-format. + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature */ - char *receiver_wire_account; + struct TALER_ExtensionPolicyHashP h_policy; /** - * Salt used to compute h_wire from the @e receiver_wire_account. + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. */ - struct TALER_WireSaltP wire_salt; + struct TALER_Amount amount_with_fee; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; /** * Time when this request was generated. Used, for example, to @@ -1495,15 +2054,25 @@ struct TALER_EXCHANGEDB_DepositListEntry struct GNUNET_TIME_Timestamp wire_deadline; /** - * Fraction of the coin's remaining value to be deposited, including - * depositing fee (if any). The coin is identified by @e coin_pub. + * Detailed information about the receiver for executing the transaction. + * URL in payto://-format. */ - struct TALER_Amount amount_with_fee; + char *receiver_wire_account; /** - * Depositing fee. + * true, if age commitment is not applicable */ - struct TALER_Amount deposit_fee; + bool no_age_commitment; + + /** + * true, if wallet data hash is not present + */ + bool no_wallet_data_hash; + + /** + * True if a policy was provided with the deposit request + */ + bool has_policy; /** * Has the deposit been wired? @@ -1729,6 +2298,56 @@ struct TALER_EXCHANGEDB_PurseDepositListEntry /** + * @brief Specification for a purse refund operation in a coin's transaction list. + */ +struct TALER_EXCHANGEDB_PurseRefundListEntry +{ + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Fraction of the original deposit's value to be refunded, including + * refund fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount refund_amount; + + /** + * Refund fee to be covered by the customer. + */ + struct TALER_Amount refund_fee; + +}; + + +/** + * Information about a /reserves/$RID/open operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_ReserveOpenListEntry +{ + + /** + * Signature of the reserve. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Contribution of the coin to the open fee, including + * deposit fee. + */ + struct TALER_Amount coin_contribution; + + /** + * Signature by the coin affirming the open deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + +}; + + +/** * Information about a /purses/$PID/deposit operation. */ struct TALER_EXCHANGEDB_PurseDeposit @@ -1830,9 +2449,9 @@ struct TALER_EXCHANGEDB_LinkList struct TALER_CoinSpendSignatureP orig_coin_link_sig; /** - * CS nonce, if cipher is CS. + * Session nonce, if cipher has one. */ - struct TALER_CsNonce nonce; + union GNUNET_CRYPTO_BlindSessionNonce nonce; /** * Offset that generated this coin in the refresh @@ -1887,7 +2506,17 @@ enum TALER_EXCHANGEDB_TransactionType /** * Purse deposit operation. */ - TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6 + TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6, + + /** + * Purse deposit operation. + */ + TALER_EXCHANGEDB_TT_PURSE_REFUND = 7, + + /** + * Reserve open deposit operation. + */ + TALER_EXCHANGEDB_TT_RESERVE_OPEN = 8 }; @@ -1963,6 +2592,18 @@ struct TALER_EXCHANGEDB_TransactionList */ struct TALER_EXCHANGEDB_PurseDepositListEntry *purse_deposit; + /** + * Coin was refunded upon purse expiration + * (#TALER_EXCHANGEDB_TT_PURSE_REFUND) + */ + struct TALER_EXCHANGEDB_PurseRefundListEntry *purse_refund; + + /** + * Coin was used to pay to open a reserve. + * (#TALER_EXCHANGEDB_TT_RESERVE_OPEN) + */ + struct TALER_EXCHANGEDB_ReserveOpenListEntry *reserve_open; + } details; }; @@ -1986,6 +2627,28 @@ typedef void /** + * Callback with KYC attributes about a particular user. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param provider_section provider that must be checked + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + */ +typedef void +(*TALER_EXCHANGEDB_AttributeCallback)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + struct GNUNET_TIME_Timestamp collection_time, + struct GNUNET_TIME_Timestamp expiration_time, + size_t enc_attributes_size, + const void *enc_attributes); + + +/** * Function called with details about deposits that have been made, * with the goal of auditing the deposit's execution. * @@ -2103,42 +2766,41 @@ typedef enum GNUNET_GenericReturnValue /** - * Function called with details about - * history requests that have been made, with - * the goal of auditing the history request execution. + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. * * @param cls closure * @param rowid unique serial ID for the deposit in our DB - * @param history_fee fee paid for the request - * @param ts timestamp of the request - * @param reserve_pub reserve history was requested for - * @param reserve_sig signature approving the @a history_fee + * @param purse_pub public key of the purse + * @param reserve_pub public key of the target reserve, NULL if not known / refunded + * @param purse_value what is the (target) value of the purse * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ typedef enum GNUNET_GenericReturnValue -(*TALER_EXCHANGEDB_HistoryRequestCallback)( +(*TALER_EXCHANGEDB_PurseDecisionCallback)( void *cls, uint64_t rowid, - const struct TALER_Amount *history_fee, - const struct GNUNET_TIME_Timestamp ts, + const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig); + const struct TALER_Amount *purse_value); /** - * Function called with details about purse refunds that have been made, with - * the goal of auditing the purse refund's execution. + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. * * @param cls closure * @param rowid unique serial ID for the deposit in our DB - * @param purse_pub public key of the refunded purse + * @param purse_pub public key of the purse + * @param refunded true if decision was to refund * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ typedef enum GNUNET_GenericReturnValue -(*TALER_EXCHANGEDB_PurseRefundCallback)( +(*TALER_EXCHANGEDB_AllPurseDecisionCallback)( void *cls, uint64_t rowid, - const struct TALER_PurseContractPublicKeyP *purse_pub); + const struct TALER_PurseContractPublicKeyP *purse_pub, + bool refunded); /** @@ -2273,15 +2935,14 @@ struct TALER_EXCHANGEDB_CsRevealFreshCoinData /** * Generic KYC status for some operation. - * @deprecated FIXME - remove with new KYC logic */ struct TALER_EXCHANGEDB_KycStatus { /** - * Number that identifies the KYC target the operation + * Number that identifies the KYC requirement the operation * was about. */ - uint64_t legitimization_uuid; + uint64_t requirement_row; /** * True if the KYC status is "satisfied". @@ -2291,6 +2952,17 @@ struct TALER_EXCHANGEDB_KycStatus }; +struct TALER_EXCHANGEDB_ReserveInInfo +{ + const struct TALER_ReservePublicKeyP *reserve_pub; + const struct TALER_Amount *balance; + struct GNUNET_TIME_Timestamp execution_time; + const char *sender_account_details; + const char *exchange_account_name; + uint64_t wire_reference; +}; + + /** * Function called on each @a amount that was found to * be relevant for a KYC check. @@ -2382,14 +3054,24 @@ typedef enum GNUNET_GenericReturnValue * * @param cls closure * @param payto_uri the exchange bank account URI + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account + * @param credit_restrictions JSON array with credit restrictions on the account * @param master_sig master key signature affirming that this is a bank * account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS) + * @param bank_label label the wallet should use to display the account, can be NULL + * @param priority priority for ordering bank account labels */ typedef void (*TALER_EXCHANGEDB_WireAccountCallback)( void *cls, const char *payto_uri, - const struct TALER_MasterSignatureP *master_sig); + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); /** @@ -2417,7 +3099,6 @@ typedef void * @param cls closure * @param fees the global fees we charge * @param purse_timeout when do purses time out - * @param kyc_timeout when do reserves without KYC time out * @param history_expiration how long are account histories preserved * @param purse_account_limit how many purses are free per account * @param start_date from when are these fees valid (start date) @@ -2430,7 +3111,6 @@ typedef void void *cls, const struct TALER_GlobalFeeSet *fees, struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative kyc_timeout, struct GNUNET_TIME_Relative history_expiration, uint32_t purse_account_limit, struct GNUNET_TIME_Timestamp start_date, @@ -2595,7 +3275,7 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); /** @@ -2625,7 +3305,34 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); + + +/** + * Function called about reserve opening operations. + * + * @param cls closure + * @param rowid row identifier used to uniquely identify the reserve closing operation + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_pub public key of the reserve + * @param reserve_sig signature affirming the operation + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_ReserveOpenCallback)( + void *cls, + uint64_t rowid, + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); /** @@ -2640,6 +3347,8 @@ typedef enum GNUNET_GenericReturnValue * @param reserve_pub public key of the reserve * @param receiver_account where did we send the funds, in payto://-format * @param wtid identifier used for the wire transfer + * @param close_request_row row with the responsible close + * request, 0 if regular expiration triggered close * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ typedef enum GNUNET_GenericReturnValue @@ -2651,7 +3360,8 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_Amount *closing_fee, const struct TALER_ReservePublicKeyP *reserve_pub, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid); + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t close_request_row); /** @@ -2674,15 +3384,20 @@ typedef void * @param left amount left in the reserve * @param account_details information about the reserve's bank account, in payto://-format * @param expiration_date when did the reserve expire - * @return transaction status code to pass on + * @param close_request_row row that caused the reserve + * to be closed, 0 if it expired without request + * @return #GNUNET_OK on success, + * #GNUNET_NO to retry + * #GNUNET_SYSERR on hard failures (exit) */ -typedef enum GNUNET_DB_QueryStatus +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveExpiredCallback)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *left, const char *account_details, - struct GNUNET_TIME_Timestamp expiration_date); + struct GNUNET_TIME_Timestamp expiration_date, + uint64_t close_request_row); /** @@ -2703,32 +3418,72 @@ typedef void uint64_t rowid, const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind, + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind, const struct TALER_BlindedCoinHashP *h_blinded_ev, const struct TALER_Amount *amount); /** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. + * Function called on (batch) deposits will need a wire + * transfer. * * @param cls closure - * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin - * @param amount value of the deposit, including fee - * @param payto_uri where should the funds be wired; URI in payto://-format - * @param deadline what was the requested wire transfer deadline - * @param done did the exchange claim that it made a transfer? + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline */ typedef void (*TALER_EXCHANGEDB_WireMissingCallback)( void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline); + + +/** + * Function called on aggregations that were done for + * a (batch) deposit. + * + * @param cls closure + * @param tracking_serial_id where in the table are we + * @param batch_deposit_serial_id which batch deposit was aggregated + */ +typedef void +(*TALER_EXCHANGEDB_AggregationCallback)( + void *cls, + uint64_t tracking_serial_id, + uint64_t batch_deposit_serial_id); + + +/** + * Function called on purse requests. + * + * @param cls closure + * @param rowid purse request table row of the purse + * @param purse_pub public key of the purse + * @param merge_pub public key representing the merge capability + * @param purse_creation when was the purse created? + * @param purse_expiration when would an unmerged purse expire + * @param h_contract_terms contract associated with the purse + * @param age_limit the age limit for deposits into the purse + * @param target_amount amount to be put into the purse + * @param purse_sig signature of the purse over the initialization data + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRequestCallback)( + void *cls, uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const char *payto_uri, - struct GNUNET_TIME_Timestamp deadline, - bool done); + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_creation, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + const struct TALER_Amount *target_amount, + const struct TALER_PurseContractSignatureP *purse_sig); /** @@ -2748,6 +3503,46 @@ typedef void /** + * Return AML status. + * + * @param cls closure + * @param row_id current row in AML status table + * @param h_payto account for which the attribute data is stored + * @param threshold currently monthly threshold that would trigger an AML check + * @param status what is the current AML decision + */ +typedef void +(*TALER_EXCHANGEDB_AmlStatusCallback)( + void *cls, + uint64_t row_id, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold, + enum TALER_AmlDecisionState status); + + +/** + * Return historic AML decision. + * + * @param cls closure + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + */ +typedef void +(*TALER_EXCHANGEDB_AmlHistoryCallback)( + void *cls, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig); + + +/** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. */ @@ -2779,49 +3574,17 @@ struct TALER_EXCHANGEDB_Plugin * Create the necessary tables if they are not present * * @param cls the @e cls of this struct with the plugin-specific state + * @param support_partitions true to enable partitioning support (disables foreign key constraints) + * @param num_partitions number of partitions to create, + * (0 to not actually use partitions, 1 to only + * setup a default partition, >1 for real partitions) * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*create_tables)(void *cls); + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); - /** - * Initialize the database of a shard node - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param idx the current shard index, will be appended to tables as suffix - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ - enum GNUNET_GenericReturnValue - (*create_shard_tables)(void *cls, - uint32_t idx); - - /** - * Change already present tables of the database to num partitions - * Only has an effect if there are default partitions only - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param num the number of partitions to create for each partitioned table - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ - enum GNUNET_GenericReturnValue - (*setup_partitions)(void *cls, - uint32_t num); - - /** - * Change already present tables of the database to num foreign tables on - * num foreign servers (shards). - * Only has an effect if there are default partitions only - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param num the number of shard servers to create. The shard servers - * must follow the numbering of [1-N], have the same user as - * the master and have tables named $TABLE_$N where $N is the same - * as the servers index of N. - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ - enum GNUNET_GenericReturnValue - (*setup_foreign_servers)(void *cls, - uint32_t num); /** * Start a transaction. @@ -3094,25 +3857,21 @@ struct TALER_EXCHANGEDB_Plugin /** - * Insert a incoming transaction into reserves. New reserves are + * Insert a batch of incoming transaction into reserves. New reserves are * also created through this function. * * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param balance the amount that has to be added to the reserve - * @param execution_time when was the amount added - * @param sender_account_details information about the sender's bank account, in payto://-format - * @param wire_reference unique reference identifying the wire transfer - * @return transaction status code + * @param reserves + * @param reserves_length length of the @a reserves array + * @param[out] results array of transaction status codes of length @a reserves_length, + * set to the status of the */ enum GNUNET_DB_QueryStatus - (*reserves_in_insert)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *balance, - struct GNUNET_TIME_Timestamp execution_time, - const char *sender_account_details, - const char *exchange_account_name, - uint64_t wire_reference); + (*reserves_in_insert)( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results); /** @@ -3126,7 +3885,7 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*lock_nonce)(void *cls, - const struct TALER_CsNonce *nonce, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, const struct TALER_DenominationHashP *denom_pub_hash, const union TALER_EXCHANGEDB_NonceLockTargetP *target); @@ -3145,34 +3904,18 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_withdraw_info)(void *cls, const struct TALER_BlindedCoinHashP *bch, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + struct TALER_EXCHANGEDB_CollectableBlindcoin * + collectable); /** - * Perform withdraw operation, checking for sufficient balance - * and possibly persisting the withdrawal details. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals - * @param collectable corresponding collectable coin (blind signature) - * @param now current time (rounded) - * @param[out] found set to true if the reserve was found - * @param[out] balance_ok set to true if the balance was sufficient - * @param[out] nonce_ok set to false if the nonce was reused - * @param[out] ruuid set to the reserve's UUID (reserves table row) - * @return query execution status + * FIXME: merge do_batch_withdraw and do_batch_withdraw_insert into one API, + * which takes as input (among others) + * - denom_serial[] + * - blinded_coin_evs[] + * - denom_sigs[] + * The implementation should persist the data as _arrays_ in the DB. */ - enum GNUNET_DB_QueryStatus - (*do_withdraw)( - void *cls, - const struct TALER_CsNonce *nonce, - const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, - struct GNUNET_TIME_Timestamp now, - bool *found, - bool *balance_ok, - bool *nonce_ok, - uint64_t *ruuid); - /** * Perform reserve update as part of a batch withdraw operation, checking @@ -3183,8 +3926,12 @@ struct TALER_EXCHANGEDB_Plugin * @param now current time (rounded) * @param reserve_pub public key of the reserve to debit * @param amount total amount to withdraw + * @param do_age_check if set, the batch-withdrawal can only succeed when the reserve has no age restriction (birthday) set. * @param[out] found set to true if the reserve was found * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if no age requirements were defined on the reserve or @e do_age_check was false + * @param[out] allowed_maximum_age when @e age_ok is false, set to the allowed maximum age for withdrawal from the reserve. The client MUST then use the age-withdraw endpoint * @param[out] ruuid set to the reserve's UUID (reserves table row) * @return query execution status */ @@ -3194,8 +3941,12 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp now, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *amount, + bool do_age_check, bool *found, bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, uint64_t *ruuid); @@ -3216,7 +3967,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*do_batch_withdraw_insert)( void *cls, - const struct TALER_CsNonce *nonce, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, struct GNUNET_TIME_Timestamp now, uint64_t ruuid, @@ -3224,31 +3975,108 @@ struct TALER_EXCHANGEDB_Plugin bool *conflict, bool *nonce_reuse); + /** + * Locate the response for a age-withdraw request under a hash of the + * commitment and reserve_pub that uniquely identifies the age-withdraw + * operation. Used to ensure idempotency of the request. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the reserve for which the age-withdraw request is made + * @param ach hash that uniquely identifies the age-withdraw operation + * @param[out] aw corresponding details of the previous age-withdraw request if an entry was found + * @return statement execution status + */ + enum GNUNET_DB_QueryStatus + (*get_age_withdraw)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AgeWithdrawCommitmentHashP *ach, + struct TALER_EXCHANGEDB_AgeWithdraw *aw); + + /** + * Perform an age-withdraw operation, checking for sufficient balance and + * fulfillment of age requirements and possibly persisting the withdrawal + * details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param commitment corresponding commitment for the age-withdraw + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if age requirements were met + * @param[out] allowed_maximum_age if @e age_ok is FALSE, this is set to the allowed maximum age + * @param[out] reserve_birthday if @e age_ok is FALSE, this is set to the reserve's birthday + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_age_withdraw)( + void *cls, + const struct TALER_EXCHANGEDB_AgeWithdraw *commitment, + struct GNUNET_TIME_Timestamp now, + bool *found, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, + uint32_t *reserve_birthday, + bool *conflict); + + /** + * Retrieve the details to a policy given by its hash_code + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param hc Hash code that identifies the policy + * @param[out] detail retrieved policy details + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*get_policy_details)( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *detail); + + /** + * Persist the policy details that extends a deposit. The particular policy + * - referenced by details->hash_code - might already exist in the table, in + * which case the call will update the contents of the record with @e details + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param details The parsed `struct TALER_PolicyDetails` according to the responsible policy extension. + * @param[out] policy_details_serial_id The ID of the entry in the policy_details table + * @param[out] accumulated_total The total amount accumulated in that policy + * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*persist_policy_details)( + void *cls, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state); + /** * Perform deposit operation, checking for sufficient balance * of the coin and possibly persisting the deposit details. * * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param deposit deposit operation details - * @param known_coin_id row of the coin in the known_coins table - * @param h_payto hash of the merchant's payto URI - * @param extension_blocked true if an extension is blocking the wire transfer + * @param bd batch deposit operation details * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) * @param[out] balance_ok set to true if the balance was sufficient - * @param[out] in_conflict set to true if the deposit conflicted + * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient, + * only used if @a balance_ok is set to false. + * @param[out] ctr_conflict set to true if the same contract terms hash was previously submitted with other meta data (deadlines, wallet_data_hash, wire data etc.) * @return query execution status */ enum GNUNET_DB_QueryStatus (*do_deposit)( void *cls, - const struct TALER_EXCHANGEDB_Deposit *deposit, - uint64_t known_coin_id, - const struct TALER_PaytoHashP *h_payto, - bool extension_blocked, + const struct TALER_EXCHANGEDB_BatchDeposit *bd, struct GNUNET_TIME_Timestamp *exchange_timestamp, bool *balance_ok, - bool *in_conflict); + uint32_t *bad_balance_index, + bool *ctr_conflict); /** @@ -3275,6 +4103,19 @@ struct TALER_EXCHANGEDB_Plugin /** + * Add a proof of fulfillment of an policy + * + * @param cls the plugin-specific state + * @param[in,out] fulfillment The proof of fulfillment and serial_ids of the policy_details along with their new state and potential new amounts. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*add_policy_fulfillment_proof)( + void *cls, + struct TALER_PolicyFulfillmentTransactionData *fulfillment); + + + /** * Check if the given @a nonce was properly locked to the given @a old_coin_pub. If so, check if we already * created CS signatures for the given @a nonce and @a new_denom_pub_hashes, * and if so, return them in @a s_scalars. Otherwise, persist the @@ -3290,7 +4131,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*cs_refreshes_reveal)( void *cls, - const struct TALER_CsNonce *nonce, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, unsigned int num_fresh_coins, struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds); @@ -3343,7 +4184,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, uint64_t reserve_out_serial_id, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t known_coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, @@ -3373,7 +4214,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, uint64_t rrc_serial, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t known_coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, @@ -3383,11 +4224,18 @@ struct TALER_EXCHANGEDB_Plugin /** - * Get all of the transaction history associated with the specified - * reserve. + * Compile a list of (historic) transactions performed with the given reserve + * (withdraw, incoming wire, open, close operations). Should return 0 if the @a + * reserve_pub is unknown, otherwise determine @a etag_out and if it is past @a + * etag_in return the history after @a start_off. @a etag_out should be set + * to the last row ID of the given @a reserve_pub in the reserve history table. * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve + * @param start_off maximum starting offset in history to exclude from returning + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub * @param[out] balance set to the reserve balance * @param[out] rhp set to known transaction history (NULL if reserve is unknown) * @return transaction status @@ -3395,32 +4243,14 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_reserve_history)(void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, struct TALER_Amount *balance, struct TALER_EXCHANGEDB_ReserveHistory **rhp); /** - * Get truncated transaction history associated with the specified - * reserve. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param[out] balance_in set to the total of inbound - * transactions in the returned history - * @param[out] balance_out set to the total of outbound - * transactions in the returned history - * @param[out] rhp set to known transaction history (NULL if reserve is unknown) - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*get_reserve_status)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance_in, - struct TALER_Amount *balance_out, - struct TALER_EXCHANGEDB_ReserveHistory **rhp); - - - /** * The current reserve balance of the specified reserve. * * @param cls the @e cls of this struct with the plugin-specific state @@ -3495,9 +4325,20 @@ struct TALER_EXCHANGEDB_Plugin TALER_EXCHANGEDB_CKS_DENOM_CONFLICT = -3, /** + * Conflicting coin (expected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL = -4, + + /** + * Conflicting coin (unexpected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL = -5, + + /** * Conflicting coin (different age hash) already in database. */ - TALER_EXCHANGEDB_CKS_AGE_CONFLICT = -4, + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS = -6, + } (*ensure_coin_known)(void *cls, const struct TALER_CoinPublicInfo *coin, @@ -3507,10 +4348,30 @@ struct TALER_EXCHANGEDB_Plugin /** + * Make sure the array of given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin array of coins that must be made known + * @param[out] result array where to store information about each coin + * @param coin_length length of the @a coin and @a result arraysf + * @param batch_size desired (maximum) batch size + * @return database transaction status, non-negative on success + */ + enum GNUNET_DB_QueryStatus + (*batch_ensure_coin_known)( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); + + + /** * Retrieve information about the given @a coin from the database. * * @param cls database connection plugin state - * @param coin the coin that must be made known + * @param coin_pub the coin that must be made known + * @param[out] coin_info detailed information about the coin * @return database transaction status, non-negative on success */ enum GNUNET_DB_QueryStatus @@ -3518,6 +4379,21 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinPublicInfo *coin_info); + /** + * Retrieve the signature and corresponding denomination for a given @a coin + * from the database + * + * @param cls database connection plugin state + * @param coin_pub the public key of the coin we search for + * @param[out] denom_pub the public key of the denomination that the coin was signed with + * @param[out] denom_sig the signature with the denomination's private key over the coin_pub + */ + enum GNUNET_DB_QueryStatus + (*get_signature_for_known_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationSignature *denom_sig); /** * Retrieve the denomination of a known coin. @@ -3536,6 +4412,25 @@ struct TALER_EXCHANGEDB_Plugin /** + * Try to retrieve the salted hash of the merchant's bank account to a + * deposit contract. Used in case of conflicts for a given (merchant_pub, + * h_contract_terms) to provide the client the necessary input to retrieve + * more details about the conflict. + * + * @param cls the plugin closure + * @param merchant_pub public key of the merchant + * @param h_contract_terms contract to check for + * @param[out] h_wire hash of the wire details + */ + enum GNUNET_DB_QueryStatus + (*get_wire_hash_for_contract)( + void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct TALER_MerchantWireHashP *h_wire); + + + /** * Check if we have the specified deposit already in the database. * * @param cls the `struct PostgresClosure` with the plugin-specific state @@ -3564,21 +4459,6 @@ struct TALER_EXCHANGEDB_Plugin /** - * Insert information about deposited coin into the database. - * Used in tests and for benchmarking. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param exchange_timestamp time the exchange received the deposit request - * @param deposit deposit information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_deposit)(void *cls, - struct GNUNET_TIME_Timestamp exchange_timestamp, - const struct TALER_EXCHANGEDB_Deposit *deposit); - - - /** * Insert information about refunded coin into the database. * Used in tests and for benchmarking. * @@ -3603,12 +4483,13 @@ struct TALER_EXCHANGEDB_Plugin * @return query result status */ enum GNUNET_DB_QueryStatus - (*select_refunds_by_coin)(void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_PrivateContractHashP *h_contract, - TALER_EXCHANGEDB_RefundCoinCallback cb, - void *cb_cls); + (*select_refunds_by_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls); /** @@ -3632,13 +4513,6 @@ struct TALER_EXCHANGEDB_Plugin char **payto_uri); -/** - * Maximum number of results we return from iterate_matching_deposits(). - * - * Limit on the number of transactions we aggregate at once. - */ -#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000 - /** * Aggregate all matching deposits for @a h_payto and * @a merchant_pub, returning the total amounts. @@ -3667,6 +4541,7 @@ struct TALER_EXCHANGEDB_Plugin * @param exchange_account_section exchange account to use * @param merchant_pub public key of the merchant * @param wtid the raw wire transfer identifier to be used + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none * @param total amount to be wired in the future * @return transaction status */ @@ -3677,6 +4552,7 @@ struct TALER_EXCHANGEDB_Plugin const char *exchange_account_section, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, const struct TALER_Amount *total); @@ -3725,6 +4601,7 @@ struct TALER_EXCHANGEDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param h_payto destination of the wire transfer * @param wtid the raw wire transfer identifier to update + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none * @param total new total amount to be wired in the future * @return transaction status */ @@ -3733,6 +4610,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_PaytoHashP *h_payto, const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, const struct TALER_Amount *total); @@ -3832,18 +4710,35 @@ struct TALER_EXCHANGEDB_Plugin /** - * Compile a list of all (historic) transactions performed - * with the given coin (melt, refund, recoup and deposit operations). + * Compile a list of (historic) transactions performed with the given coin + * (melt, refund, recoup and deposit operations). Should return 0 if the @a + * coin_pub is unknown, otherwise determine @a etag_out and if it is past @a + * etag_in return the history after @a start_off. @a etag_out should be set + * to the last row ID of the given @a coin_pub in the coin history table. * * @param cls the @e cls of this struct with the plugin-specific state * @param coin_pub coin to investigate - * @param[out] tlp set to list of transactions, NULL if coin is fresh + * @param start_off starting offset from which on to return entries + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub + * @param[out] balance set to current balance of the coin + * @param[out] h_denom_pub set to denomination public key of the coin + * @param[out] tlp set to list of transactions, set to NULL if coin has no + * transaction history past @a start_off or if @a etag_in is equal + * to the value written to @a etag_out. * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*get_coin_transactions)(void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_EXCHANGEDB_TransactionList **tlp); + (*get_coin_transactions)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_TransactionList **tlp); /** @@ -3892,6 +4787,7 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] execution_time when was the transaction done, or * when we expect it to be done (if @a pending is false) * @param[out] kyc set to the kyc status of the receiver (if @a pending) + * @param[out] aml_decision set to the current AML status for the target account * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -3906,22 +4802,8 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp *exec_time, struct TALER_Amount *amount_with_fee, struct TALER_Amount *deposit_fee, - struct TALER_EXCHANGEDB_KycStatus *kyc); - - - /** - * Function called to insert aggregation information into the DB. - * - * @param cls closure - * @param wtid the raw wire transfer identifier we used - * @param deposit_serial_id row in the deposits table for which this is aggregation data - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_aggregation_tracking)( - void *cls, - const struct TALER_WireTransferIdentifierRawP *wtid, - unsigned long long deposit_serial_id); + struct TALER_EXCHANGEDB_KycStatus *kyc, + enum TALER_AmlDecisionState *aml_decision); /** @@ -3952,7 +4834,6 @@ struct TALER_EXCHANGEDB_Plugin * @param end_date when does the fees end being valid * @param fees how high is are the global fees * @param purse_timeout when do purses time out - * @param kyc_timeout when do reserves without KYC time out * @param history_expiration how long are account histories preserved * @param purse_account_limit how many purses are free per account * @param master_sig signature over the above by the exchange master key @@ -3964,7 +4845,6 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp end_date, const struct TALER_GlobalFeeSet *fees, struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative kyc_timeout, struct GNUNET_TIME_Relative history_expiration, uint32_t purse_account_limit, @@ -4002,7 +4882,6 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] end_date when does the fee end being valid * @param[out] fees how high are the global fees * @param[out] purse_timeout when do purses time out - * @param[out] kyc_timeout when do reserves without KYC time out * @param[out] history_expiration how long are account histories preserved * @param[out] purse_account_limit how many purses are free per account * @param[out] master_sig signature over the above by the exchange master key @@ -4015,7 +4894,6 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp *end_date, struct TALER_GlobalFeeSet *fees, struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *kyc_timeout, struct GNUNET_TIME_Relative *history_expiration, uint32_t *purse_account_limit, struct TALER_MasterSignatureP *master_sig); @@ -4039,6 +4917,152 @@ struct TALER_EXCHANGEDB_Plugin /** + * Obtain information about force-closed reserves + * where the close was not yet done (and their remaining + * balances). Updates the returned reserve's close + * status to "done". + * + * @param cls closure of the plugin + * @param rec function to call on (to be) closed reserves + * @param rec_cls closure for @a rec + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_unfinished_close_requests)( + void *cls, + TALER_EXCHANGEDB_ReserveExpiredCallback rec, + void *rec_cls); + + + /** + * Insert reserve open coin deposit data into database. + * Subtracts the @a coin_total from the coin's balance. + * + * @param cls closure + * @param cpi public information about the coin + * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT + * @param known_coin_id ID of the coin in the known_coins table + * @param coin_total amount to be spent of the coin (including deposit fee) + * @param reserve_sig signature by the reserve affirming the open operation + * @param reserve_pub public key of the reserve being opened + * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false + * @return transaction status code, 0 if operation is already in the DB + */ + enum GNUNET_DB_QueryStatus + (*insert_reserve_open_deposit)( + void *cls, + const struct TALER_CoinPublicInfo *cpi, + const struct TALER_CoinSpendSignatureP *coin_sig, + uint64_t known_coin_id, + const struct TALER_Amount *coin_total, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *insufficient_funds); + + + /** + * Insert reserve close operation into database. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param total_paid total amount paid (coins and reserve) + * @param reserve_payment amount to be paid from the reserve + * @param min_purse_limit minimum number of purses we should be able to open + * @param reserve_sig signature by the reserve for the operation + * @param desired_expiration when should the reserve expire (earliest time) + * @param now when did we the client initiate the action + * @param open_fee annual fee to be charged for the open operation by the exchange + * @param[out] no_funds set to true if reserve balance is insufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] open_cost set to the actual cost + * @param[out] final_expiration when will the reserve expire now + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_reserve_open)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, + uint32_t min_purse_limit, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp desired_expiration, + struct GNUNET_TIME_Timestamp now, + const struct TALER_Amount *open_fee, + bool *no_funds, + struct TALER_Amount *reserve_balance, + struct TALER_Amount *open_cost, + struct GNUNET_TIME_Timestamp *final_expiration); + + + /** + * Select information needed to see if we can close + * a reserve. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param[out] balance current reserve balance + * @param[out] payto_uri set to URL of account that + * originally funded the reserve; + * could be set to NULL if not known + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance, + char **payto_uri); + + + /** + * Select information about reserve close requests. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param rowid row ID of the close request + * @param[out] reserve_sig reserve signature affirming + * @param[out] request_timestamp when was the request made + * @param[out] close_balance reserve balance at close time + * @param[out] close_fee closing fee to be charged + * @param[out] payto_uri set to URL of account that + * should receive the money; + * could be set to NULL for origin + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_request_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t rowid, + struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *close_balance, + struct TALER_Amount *close_fee, + char **payto_uri); + + + /** + * Select information needed for KYC checks on reserve close: historic + * reserve closures going to the same account. + * + * @param cls closure + * @param h_payto which target account is this about? + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*iterate_reserve_close_info)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** * Insert reserve close operation into database. * * @param cls closure @@ -4048,6 +5072,7 @@ struct TALER_EXCHANGEDB_Plugin * @param wtid identifier for the wire transfer * @param amount_with_fee amount we charged to the reserve * @param closing_fee how high is the closing fee + * @param close_request_row identifies explicit close request, 0 for none * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -4055,9 +5080,11 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_ReservePublicKeyP *reserve_pub, struct GNUNET_TIME_Timestamp execution_date, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid, + const struct + TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *closing_fee); + const struct TALER_Amount *closing_fee, + uint64_t close_request_row); /** @@ -4177,10 +5204,29 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_deposits_above_serial_id)(void *cls, - uint64_t serial_id, - TALER_EXCHANGEDB_DepositCallback cb, - void *cb_cls); + (*select_coin_deposits_above_serial_id)(void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls); + + + /** + * Function called to return meta data about a purses + * above a certain serial ID. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param serial_id number to select requests by + * @param cb function to call on each request + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_requests_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseRequestCallback cb, + void *cb_cls); + /** * Select purse deposits above @a serial_id in monotonically increasing @@ -4237,25 +5283,27 @@ struct TALER_EXCHANGEDB_Plugin /** - * Select history requests above @a serial_id in monotonically increasing + * Select purse refunds above @a serial_id in monotonically increasing * order. * * @param cls closure * @param serial_id highest serial ID to exclude (select strictly larger) + * @param refunded which refund status to select for * @param cb function to call on each result * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_history_requests_above_serial_id)( + (*select_purse_decisions_above_serial_id)( void *cls, uint64_t serial_id, - TALER_EXCHANGEDB_HistoryRequestCallback cb, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, void *cb_cls); /** - * Select purse refunds above @a serial_id in monotonically increasing + * Select all purse refunds above @a serial_id in monotonically increasing * order. * * @param cls closure @@ -4265,10 +5313,10 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_purse_refunds_above_serial_id)( + (*select_all_purse_decisions_above_serial_id)( void *cls, uint64_t serial_id, - TALER_EXCHANGEDB_PurseRefundCallback cb, + TALER_EXCHANGEDB_AllPurseDecisionCallback cb, void *cb_cls); @@ -4392,7 +5440,8 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_wire_out_above_serial_id)(void *cls, uint64_t serial_id, - TALER_EXCHANGEDB_WireTransferOutCallback cb, + TALER_EXCHANGEDB_WireTransferOutCallback + cb, void *cb_cls); /** @@ -4451,8 +5500,8 @@ struct TALER_EXCHANGEDB_Plugin /** - * Function called to select reserve close operations the aggregator - * triggered, ordered by serial ID (monotonically increasing). + * Function called to select reserve open operations, ordered by serial ID + * (monotonically increasing). * * @param cls closure * @param serial_id lowest serial ID to include (select larger or equal) @@ -4461,6 +5510,24 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus + (*select_reserve_open_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveOpenCallback cb, + void *cb_cls); + + + /** + * Function called to select reserve close operations the aggregator + * triggered, ordered by serial ID (monotonically increasing). + * + * @param cls closure + * @param serial_id lowest serial ID to include (select larger or equal) + * @param cb function to call + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus (*select_reserve_closed_above_serial_id)( void *cls, uint64_t serial_id, @@ -4479,10 +5546,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_by_h_blind)(void *cls, - const struct TALER_BlindedCoinHashP *bch, - struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t *reserve_out_serial_id); + (*get_reserve_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id); /** @@ -4496,10 +5564,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_old_coin_by_h_blind)(void *cls, - const struct TALER_BlindedCoinHashP *h_blind_ev, - struct TALER_CoinSpendPublicKeyP *old_coin_pub, - uint64_t *rrc_serial); + (*get_old_coin_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *rrc_serial); /** @@ -4537,23 +5606,63 @@ struct TALER_EXCHANGEDB_Plugin /** - * Select all of those deposits in the database for which we do - * not have a wire transfer (or a refund) and which should have - * been deposited between @a start_date and @a end_date. + * Select all (batch) deposits in the database + * above a given @a min_batch_deposit_serial_id. * * @param cls closure - * @param start_date lower bound on the requested wire execution date - * @param end_date upper bound on the requested wire execution date + * @param min_batch_deposit_serial_id only return entries strictly above this row (and in order) * @param cb function to call on all such deposits * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_deposits_missing_wire)(void *cls, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls); + (*select_batch_deposits_missing_wire)( + void *cls, + uint64_t min_batch_deposit_serial_id, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls); + + + /** + * Select all aggregation tracking IDs in the database + * above a given @a min_tracking_serial_id. + * + * @param cls closure + * @param min_tracking_serial_id only return entries strictly above this row (and in order) + * @param cb function to call on all such aggregations + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_aggregations_above_serial)( + void *cls, + uint64_t min_tracking_serial_id, + TALER_EXCHANGEDB_AggregationCallback cb, + void *cb_cls); + + + /** + * Return any applicable justification as to why + * a wire transfer might have been held. Used + * by the auditor to determine if a wire transfer + * is legitimately stalled. + * + * @param cls closure + * @param wire_target_h_payto effected target account + * @param[out] payto_uri target account URI, set to NULL if unknown + * @param[out] kyc_pending set to string describing missing KYC data + * @param[out] status set to AML status + * @param[out] aml_limit set to AML limit, or invalid amount for none + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_justification_for_missing_wire)( + void *cls, + const struct TALER_PaytoHashP *wire_target_h_payto, + char **payto_uri, + char **kyc_pending, + enum TALER_AmlDecisionState *status, + struct TALER_Amount *aml_limit); /** @@ -4565,9 +5674,10 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*lookup_auditor_timestamp)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Timestamp *last_date); + (*lookup_auditor_timestamp)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date); /** @@ -4581,10 +5691,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*lookup_auditor_status)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - char **auditor_url, - bool *enabled); + (*lookup_auditor_status)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled); /** @@ -4599,11 +5710,12 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp start_date); + (*insert_auditor)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date); /** @@ -4619,12 +5731,13 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_auditor)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp change_date, - bool enabled); + (*update_auditor)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp change_date, + bool enabled); /** @@ -4646,17 +5759,27 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param payto_uri wire account of the exchange + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account + * @param credit_restrictions JSON array with credit restrictions on the account * @param start_date date when the account was added by the offline system * (only to be used for replay detection) * @param master_sig public signature affirming the existence of the account, * must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS + * @param bank_label label to show this entry under in the UI, can be NULL + * @param priority determines order in which entries are shown in the UI * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_wire)(void *cls, const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp start_date, - const struct TALER_MasterSignatureP *master_sig); + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); /** @@ -4664,15 +5787,27 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param payto_uri account the update is about + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account; NULL allowed if not @a enabled + * @param credit_restrictions JSON array with credit restrictions on the account; NULL allowed if not @a enabled * @param change_date date when the account status was last changed * (only to be used for replay detection) + * @param master_sig master signature to store, can be NULL (if @a enabled is false) + * @param bank_label label to show this entry under in the UI, can be NULL + * @param priority determines order in which entries are shown in the UI * @param enabled true to enable, false to disable (the actual change) * @return transaction status code */ enum GNUNET_DB_QueryStatus (*update_wire)(void *cls, const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, struct GNUNET_TIME_Timestamp change_date, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority, bool enabled); @@ -4883,7 +6018,6 @@ struct TALER_EXCHANGEDB_Plugin * different global fee exists within this time * period, an 'invalid' amount is returned. * @param[out] purse_timeout set to when unmerged purses expire - * @param[out] kyc_timeout set to when reserves without kyc expire * @param[out] history_expiration set to when we expire reserve histories * @param[out] purse_account_limit set to number of free purses * @return transaction status code @@ -4895,7 +6029,6 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp end_time, struct TALER_GlobalFeeSet *fees, struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *kyc_timeout, struct GNUNET_TIME_Relative *history_expiration, uint32_t *purse_account_limit); @@ -4939,6 +6072,7 @@ struct TALER_EXCHANGEDB_Plugin * Insert record set into @a table. Used in exchange-auditor database * replication. * + memset (&awc, 0, sizeof (awc)); * @param cls closure * @param tb table data to insert * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if @@ -5044,40 +6178,41 @@ struct TALER_EXCHANGEDB_Plugin * changed. * * @param cls the @e cls of this struct with the plugin-specific state - * @return transaction status code + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on failure */ - enum GNUNET_DB_QueryStatus + enum GNUNET_GenericReturnValue (*delete_shard_locks)(void *cls); /** - * Function called to save the configuration of an extension - * (age-restriction, peer2peer, ...) + * Function called to save the manifest of an extension + * (age-restriction, policy-extension, ...) * * @param cls the @e cls of this struct with the plugin-specific state * @param extension_name the name of the extension - * @param config JSON object of the configuration as string, maybe NULL (== disabled extension) + * @param manifest JSON object of the Manifest as string, maybe NULL (== disabled extension) * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*set_extension_config)(void *cls, - const char *extension_name, - const char *config); + (*set_extension_manifest)(void *cls, + const char *extension_name, + const char *manifest); /** - * Function called to retrieve the configuration of an extension - * (age-restriction, peer2peer, ...) + * Function called to retrieve the manifest of an extension + * (age-restriction, policy-extension, ...) * * @param cls the @e cls of this struct with the plugin-specific state * @param extension_name the name of the extension - * @param[out] config JSON object of the configuration as string, maybe NULL (== disabled extension) + * @param[out] manifest Manifest of the extension in JSON encoding, maybe NULL (== disabled extension) * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_extension_config)(void *cls, - const char *extension_name, - char **config); + (*get_extension_manifest)(void *cls, + const char *extension_name, + char **manifest); /** @@ -5214,22 +6349,28 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub public key of the new purse + * @param[out] purse_creation set to time when the purse was created * @param[out] purse_expiration set to time when the purse will expire * @param[out] amount set to target amount (with fees) to be put into the purse * @param[out] deposited set to actual amount put into the purse so far * @param[out] h_contract_terms set to hash of the contract for the purse * @param[out] merge_timestamp set to time when the purse was merged, or NEVER if not + * @param[out] purse_deleted set to true if purse was deleted + * @param[out] purse_refunded set to true if purse was refunded (after expiration) * @return transaction status code */ enum GNUNET_DB_QueryStatus (*select_purse)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_creation, struct GNUNET_TIME_Timestamp *purse_expiration, struct TALER_Amount *amount, struct TALER_Amount *deposited, struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp *merge_timestamp); + struct GNUNET_TIME_Timestamp *merge_timestamp, + bool *purse_deleted, + bool *purse_refunded); /** @@ -5248,7 +6389,7 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_purse_request)( + (*get_purse_request)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, struct TALER_PurseMergePublicKeyP *merge_pub, @@ -5306,6 +6447,7 @@ struct TALER_EXCHANGEDB_Plugin * remaining balance is below @a amount; * in this case, the return value will be * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @param[out] too_late it is too late to deposit into this purse * @param[out] conflict the same coin was deposited into * this purse with a different amount already * @return transaction status code @@ -5319,10 +6461,32 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_Amount *amount_minus_fee, bool *balance_ok, + bool *too_late, bool *conflict); /** + * Function called to explicitly delete a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to delete + * @param purse_sig signature affirming the deletion + * @param[out] decided set to true if the purse was + * already decided and thus could not be deleted + * @param[out] found set to true if the purse was found + * (if false, purse could not be deleted) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_delete)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *decided, + bool *found); + + + /** * Set the current @a balance in the purse * identified by @a purse_pub. Used by the auditor * to update the balance as calculated by the auditor. @@ -5438,6 +6602,7 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] merge_timestamp set to the time of the merge * @param[out] partner_url set to the URL of the target exchange, or NULL if the target exchange is us. To be freed by the caller. * @param[out] reserve_pub set to the public key of the reserve/account being credited + * @param[out] refunded set to true if purse was refunded * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -5447,34 +6612,8 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_PurseMergeSignatureP *merge_sig, struct GNUNET_TIME_Timestamp *merge_timestamp, char **partner_url, - struct TALER_ReservePublicKeyP *reserve_pub); - - - /** - * Function called to persist a signature that - * prove that the client requested an - * account history. Debits the @a history_fee from - * the reserve (if possible). - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub account that the history was requested for - * @param reserve_sig signature affirming the request - * @param request_timestamp when was the request made - * @param history_fee how much should the @a reserve_pub be charged for the request - * @param[out] balance_ok set to TRUE if the reserve balance - * was sufficient - * @param[out] idempotent set to TRUE if the request is already in the DB - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_history_request)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Timestamp request_timestamp, - const struct TALER_Amount *history_fee, - bool *balance_ok, - bool *idempotent); + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded); /** @@ -5482,17 +6621,21 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the account to close + * @param payto_uri where to wire the funds * @param reserve_sig signature affiming that the account is to be closed * @param request_timestamp timestamp of the close request - * @param[out] final_balance set to the final balance in the account that will be wired back to the origin account + * @param balance balance at the time of closing + * @param closing_fee closing fee to charge * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_close_request)(void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, + const char *payto_uri, const struct TALER_ReserveSignatureP *reserve_sig, struct GNUNET_TIME_Timestamp request_timestamp, - struct TALER_Amount *final_balance); + const struct TALER_Amount *balance, + const struct TALER_Amount *closing_fee); /** @@ -5583,84 +6726,122 @@ struct TALER_EXCHANGEDB_Plugin * Insert KYC requirement for @a h_payto account into table. * * @param cls closure - * @param provider_section provider that must be checked + * @param requirements requirements that must be checked * @param h_payto account that must be KYC'ed - * @param[out] legi_row set to legitimization row for this check + * @param reserve_pub if account is a reserve, its public key, NULL otherwise + * @param[out] requirement_row set to legitimization requirement row for this check * @return database transaction status */ enum GNUNET_DB_QueryStatus (*insert_kyc_requirement_for_account)( void *cls, - const char *provider_section, + const char *requirements, const struct TALER_PaytoHashP *h_payto, - uint64_t *legi_row); + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *requirement_row); /** - * Update KYC requirement check with provider-linkage and/or - * expiration data. + * Begin KYC requirement process. * * @param cls closure - * @param legi_row row to select by + * @param h_payto account that must be KYC'ed * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param[out] process_row row the process is stored under + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id, + uint64_t *process_row); + + + /** + * Fetch information about pending KYC requirement process. + * + * @param cls closure * @param h_payto account that must be KYC'ed + * @param provider_section provider that must be checked + * @param[out] redirect_url set to redirect URL for the process + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_pending_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + char **redirect_url); + + + /** + * Update KYC process with updated provider-linkage and/or + * expiration data. + * + * @param cls closure + * @param process_row row to select by + * @param provider_section provider that must be checked (technically redundant) + * @param h_payto account that must be KYC'ed (helps access by shard, otherwise also redundant) * @param provider_account_id provider account ID * @param provider_legitimization_id provider legitimization ID + * @param redirect_url where the user should be redirected to start the KYC process * @param expiration how long is this KYC check set to be valid (in the past if invalid) * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*update_kyc_requirement_by_row)( + (*update_kyc_process_by_row)( void *cls, - uint64_t legi_row, + uint64_t process_row, const char *provider_section, const struct TALER_PaytoHashP *h_payto, const char *provider_account_id, const char *provider_legitimization_id, + const char *redirect_url, struct GNUNET_TIME_Absolute expiration); /** - * Lookup KYC provider meta data. + * Lookup KYC requirement. * * @param cls closure - * @param legi_row legitimization row to lookup - * @param[out] provider_section provider that must be checked + * @param legi_row identifies requirement to look up + * @param[out] requirements space-separated list of requirements + * @param[out] aml_status set to the AML status of the account * @param[out] h_payto account that must be KYC'ed - * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) - * @param[out] provider_account_id provider account ID - * @param[out] provider_legitimization_id provider legitimization ID * @return database transaction status */ enum GNUNET_DB_QueryStatus (*lookup_kyc_requirement_by_row)( void *cls, - uint64_t legi_row, - char **provider_section, - struct TALER_PaytoHashP *h_payto, - struct GNUNET_TIME_Absolute *expiration, - char **provider_account_id, - char **provider_legitimization_id); + uint64_t requirement_row, + char **requirements, + enum TALER_AmlDecisionState *aml_status, + struct TALER_PaytoHashP *h_payto); /** - * Lookup KYC provider meta data. + * Lookup KYC process meta data. * * @param cls closure * @param provider_section provider that must be checked * @param h_payto account that must be KYC'ed - * @param[out] legi_row row with the legitimization data + * @param[out] process_row set to row with the legitimization data * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) * @param[out] provider_account_id provider account ID * @param[out] provider_legitimization_id provider legitimization ID * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_kyc_requirement_by_account)( + (*lookup_kyc_process_by_account)( void *cls, const char *provider_section, const struct TALER_PaytoHashP *h_payto, - uint64_t *legi_row, + uint64_t *process_row, struct GNUNET_TIME_Absolute *expiration, char **provider_account_id, char **provider_legitimization_id); @@ -5674,7 +6855,7 @@ struct TALER_EXCHANGEDB_Plugin * @param provider_section * @param provider_legitimization_id legi to look up * @param[out] h_payto where to write the result - * @param[out] legi_row where to write the row of the entry + * @param[out] process_row identifies the legitimization process on our end * @return database transaction status */ enum GNUNET_DB_QueryStatus @@ -5683,7 +6864,7 @@ struct TALER_EXCHANGEDB_Plugin const char *provider_section, const char *provider_legitimization_id, struct TALER_PaytoHashP *h_payto, - uint64_t *legi_row); + uint64_t *process_row); /** @@ -5705,6 +6886,24 @@ struct TALER_EXCHANGEDB_Plugin /** + * Call us on KYC legitimization processes satisfied and not expired for the + * given account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param lpc function to call for each satisfied KYC legitimization process + * @param lpc_cls closure for @a lpc + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_kyc_reference)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_LegitimizationProcessCallback lpc, + void *lpc_cls); + + + /** * Call @a kac on withdrawn amounts after @a time_limit which are relevant * for a KYC trigger for a the (debited) account identified by @a h_payto. * @@ -5764,6 +6963,282 @@ struct TALER_EXCHANGEDB_Plugin void *kac_cls); + /** + * Store KYC attribute data, update KYC process status and + * AML status for the given account. + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param kyc_prox key for similarity search + * @param provider_section provider that must be checked + * @param num_checks how many checks do these attributes satisfy + * @param satisfied_checks array of checks satisfied by these attributes + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + * @param require_aml true to trigger AML + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_attributes)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const struct GNUNET_ShortHashCode *kyc_prox, + const char *provider_section, + unsigned int num_checks, + const char *satisfied_checks[static num_checks], + uint32_t birthday, + struct GNUNET_TIME_Timestamp collection_time, + const char *provider_account_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration_time, + size_t enc_attributes_size, + const void *enc_attributes, + bool require_aml); + + + /** + * Lookup similar KYC attribute data. + * + * @param cls closure + * @param kyc_prox key for similarity search + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_similar_kyc_attributes)( + void *cls, + const struct GNUNET_ShortHashCode *kyc_prox, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Lookup KYC attribute data for a specific account. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_kyc_attributes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Insert AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param master_sig offline signature affirming the AML officer + * @param decider_name full name of the staff member + * @param is_active true to enable, false to set as inactive + * @param read_only true to set read-only access + * @param last_change when was the change made effective + * @param[out] previous_change when was the previous change made + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_MasterSignatureP *master_sig, + const char *decider_name, + bool is_active, + bool read_only, + struct GNUNET_TIME_Timestamp last_change, + struct GNUNET_TIME_Timestamp *previous_change); + + + /** + * Test if the given AML staff member is active + * (at least read-only). + * + * @param cls closure + * @param decider_pub public key of the staff member + * @return database transaction status, if member is unknown or not active, 1 if member is active + */ + enum GNUNET_DB_QueryStatus + (*test_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub); + + + /** + * Fetch AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param[out] master_sig offline signature affirming the AML officer + * @param[out] decider_name full name of the staff member + * @param[out] is_active true to enable, false to set as inactive + * @param[out] read_only true to set read-only access + * @param[out] last_change when was the change made effective + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + struct TALER_MasterSignatureP *master_sig, + char **decider_name, + bool *is_active, + bool *read_only, + struct GNUNET_TIME_Absolute *last_change); + + + /** + * Obtain the current AML threshold set for an account. + * + * @param cls closure + * @param h_payto account for which the AML threshold is stored + * @param[out] decision set to current AML decision + * @param[out] threshold set to the existing threshold + * @return database transaction status, 0 if no threshold was set + */ + enum GNUNET_DB_QueryStatus + (*select_aml_threshold)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState *decision, + struct TALER_EXCHANGEDB_KycStatus *kyc, + struct TALER_Amount *threshold); + + + /** + * Trigger AML process, an account has crossed the threshold. Inserts or + * updates the AML status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param threshold_crossed existing threshold that was crossed + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*trigger_aml_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold_crossed); + + + /** + * Lookup AML decisions that have a particular state. + * + * @param cls closure + * @param decision which decision states to filter by + * @param row_off offset to start from + * @param forward true to go forward in time, false to go backwards + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_process)( + void *cls, + enum TALER_AmlDecisionState decision, + uint64_t row_off, + uint64_t limit, + bool forward, + TALER_EXCHANGEDB_AmlStatusCallback cb, + void *cb_cls); + + + /** + * Lookup AML decision history for a particular account. + * + * @param cls closure + * @param h_payto which account should we return the AML decision history for + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_history)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlHistoryCallback cb, + void *cb_cls); + + + /** + * Insert an AML decision. Inserts into AML history and insert or updates AML + * status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param kyc_requirements specific KYC requirements being imposed + * @param requirements_row row in the KYC table for this process, 0 for none + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] last_date set to the previous decision time; + * the INSERT is not performed if @a last_date is not before @a decision_time + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_decision)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const json_t *kyc_requirements, + uint64_t requirements_row, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig, + bool *invalid_officer, + struct GNUNET_TIME_Timestamp *last_date); + + + /** + * Update KYC process status to finished (and failed). + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_failure)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id); + + /** + * Function called to inject auditor triggers into the + * database, triggering the real-time auditor upon + * relevant INSERTs. + * + * @param cls closure + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on DB errors + */ + enum GNUNET_GenericReturnValue + (*inject_auditor_triggers)(void *cls); + }; #endif /* _TALER_EXCHANGE_DB_H */ |