diff options
Diffstat (limited to 'src/include/taler_exchangedb_plugin.h')
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 3286 |
1 files changed, 2817 insertions, 469 deletions
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 213fe114d..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,13 +18,83 @@ * @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 #include <jansson.h> #include <gnunet/gnunet_util_lib.h> #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; +}; /** @@ -105,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 { @@ -191,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, @@ -206,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, @@ -215,7 +309,26 @@ 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_DECISION, + TALER_EXCHANGEDB_RT_PURSE_MERGES, + TALER_EXCHANGEDB_RT_PURSE_DEPOSITS, + TALER_EXCHANGEDB_RT_ACCOUNT_MERGES, + TALER_EXCHANGEDB_RT_HISTORY_REQUESTS, + TALER_EXCHANGEDB_RT_CLOSE_REQUESTS, + TALER_EXCHANGEDB_RT_WADS_OUT, + TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES, + 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, }; @@ -266,17 +379,28 @@ struct TALER_EXCHANGEDB_TableData struct { char *payto_uri; - bool kyc_ok; - char *external_id; } wire_targets; 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; - /** - * Note: not useful for auditor, because not UPDATEd! - */ - struct TALER_Amount current_balance; struct GNUNET_TIME_Timestamp expiration_date; struct GNUNET_TIME_Timestamp gc_date; } reserves; @@ -294,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; @@ -347,7 +490,6 @@ struct TALER_EXCHANGEDB_TableData struct TALER_AgeCommitmentHash age_hash; uint64_t denominations_serial; struct TALER_DenominationSignature denom_sig; - struct TALER_Amount remaining; } known_coins; struct @@ -382,27 +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 done; - 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; @@ -419,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; @@ -438,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; @@ -448,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; @@ -459,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; @@ -468,13 +615,207 @@ 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 + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergePublicKeyP merge_pub; + struct GNUNET_TIME_Timestamp purse_creation; + struct GNUNET_TIME_Timestamp purse_expiration; + struct TALER_PrivateContractHashP h_contract_terms; + uint32_t age_limit; + uint32_t flags; + struct TALER_Amount amount_with_fee; + struct TALER_Amount purse_fee; + struct TALER_PurseContractSignatureP purse_sig; + } purse_requests; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct GNUNET_TIME_Timestamp action_timestamp; + bool refunded; + } purse_decision; + + struct + { + uint64_t partner_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergeSignatureP merge_sig; + struct GNUNET_TIME_Timestamp merge_timestamp; + } purse_merges; + + struct + { + uint64_t partner_serial_id; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_Amount amount_with_fee; + struct TALER_CoinSpendSignatureP coin_sig; + } purse_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PaytoHashP wallet_h_payto; + } account_merges; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct GNUNET_TIME_Timestamp request_timestamp; + struct TALER_Amount history_fee; + } history_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + 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 + { + struct TALER_WadIdentifierP wad_id; + uint64_t partner_serial_id; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp execution_time; + } wads_out; + + struct + { + uint64_t wad_out_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_out_entries; + + struct + { + struct TALER_WadIdentifierP wad_id; + char *origin_exchange_url; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp arrival_time; + } wads_in; + + struct + { + uint64_t wad_in_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_in_entries; + + struct + { + struct TALER_WireTransferIdentifierRawP wtid; + char *account_section; + char *payto_uri; + struct GNUNET_TIME_Timestamp trigger_date; + struct TALER_Amount amount; + 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; @@ -635,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; @@ -743,6 +1091,39 @@ typedef void /** + * Function called on all KYC process names that the given + * account has already passed. + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + */ +typedef void +(*TALER_EXCHANGEDB_SatisfiedProviderCallback)( + void *cls, + const char *kyc_provider_section_name); + + +/** + * 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 *` @@ -835,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. */ @@ -850,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 @@ -904,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 @@ -952,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 @@ -979,6 +1433,173 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry /** + * Details about a purse merge operation. + */ +struct TALER_EXCHANGEDB_PurseMerge +{ + + /** + * Public key of the reserve the coin was merged into. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Amount in the purse, with fees. + */ + struct TALER_Amount amount_with_fee; + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * When was the purse set to expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * Minimum age required for depositing into the purse. + */ + uint32_t min_age; + + /** + * Flags of the purse. + */ + enum TALER_WalletAccountMergeFlags flags; + + /** + * true if the purse was actually successfully merged, + * false if the @e purse_fee was charged but the + * @e amount was not credited to the reserve. + */ + bool merged; +}; + + +/** + * Details about a (paid for) reserve history request. + */ +struct TALER_EXCHANGEDB_HistoryRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request. + */ + struct TALER_Amount history_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; +}; + + +/** + * 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 @@ -1004,7 +1625,27 @@ enum TALER_EXCHANGEDB_ReserveOperation * customer's bank account. This happens when the exchange * closes a reserve with a non-zero amount left in it. */ - TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3 + TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3, + + /** + * Event where a purse was merged into a reserve. + */ + TALER_EXCHANGEDB_RO_PURSE_MERGE = 4, + + /** + * Event where a wallet paid for a full reserve history. + */ + 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 }; @@ -1055,12 +1696,156 @@ struct TALER_EXCHANGEDB_ReserveHistory */ struct TALER_EXCHANGEDB_ClosingTransfer *closing; + /** + * Details about a purse merge operation. + */ + struct TALER_EXCHANGEDB_PurseMerge *merge; + + /** + * Details about a (paid for) reserve history request. + */ + 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 @@ -1103,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 @@ -1155,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; + }; @@ -1186,31 +1986,42 @@ 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; /** - * Age commitment hash, if applicable ot the denomination. Should be all + * Age commitment hash, if applicable to the denomination. Should be all * zeroes if age commitment is not applicable to the denonimation. */ 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 @@ -1243,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? @@ -1426,6 +2247,158 @@ struct TALER_EXCHANGEDB_MeltListEntry /** + * Information about a /purses/$PID/deposit operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_PurseDepositListEntry +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if the coin was refunded. + */ + bool refunded; + + /** + * Set to true if there was no age commitment. + */ + bool no_age_commitment; + +}; + + +/** + * @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 +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Public key of the coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. May be all zeroes if no age restriction + * applies. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if @e h_age_commitment is not available. + */ + bool no_age_commitment; + +}; + +/** * Information about a melt operation. */ struct TALER_EXCHANGEDB_Melt @@ -1476,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 @@ -1528,7 +2501,22 @@ enum TALER_EXCHANGEDB_TransactionType /** * Recoup-refresh operation (on the new coin, eliminating its value) */ - TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5 + TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5, + + /** + * Purse deposit operation. + */ + 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 }; @@ -1598,6 +2586,24 @@ struct TALER_EXCHANGEDB_TransactionList */ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup_refresh; + /** + * Coin was deposited into a purse. + * (#TALER_EXCHANGEDB_TT_PURSE_DEPOSIT) + */ + 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; }; @@ -1621,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. * @@ -1643,6 +2671,159 @@ typedef enum GNUNET_GenericReturnValue /** + * Function called with details about purse deposits that have been made, with + * the goal of auditing the deposit's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param deposit deposit details + * @param reserve_pub which reserve is the purse merged into, NULL if unknown + * @param flags purse flags + * @param auditor_balance purse balance (according to the + * auditor during auditing) + * @param purse_total target amount the purse should reach + * @param denom_pub denomination public key of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDepositCallback)( + void *cls, + uint64_t rowid, + const struct TALER_EXCHANGEDB_PurseDeposit *deposit, + const struct TALER_ReservePublicKeyP *reserve_pub, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *auditor_balance, + const struct TALER_Amount *purse_total, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Function called with details about + * account merge requests that have been made, with + * the goal of auditing the account merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param reserve_pub reserve affected by the merge + * @param purse_pub purse being merged + * @param h_contract_terms hash over contract of the purse + * @param purse_expiration when would the purse expire + * @param amount total amount in the purse + * @param min_age minimum age of all coins deposited into the purse + * @param flags how was the purse created + * @param purse_fee if a purse fee was paid, how high is it + * @param merge_timestamp when was the merge approved + * @param reserve_sig signature by reserve approving the merge + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_AccountMergeCallback)( + void *cls, + uint64_t rowid, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Function called with details about purse + * merges that have been made, with + * the goal of auditing the purse merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param partner_base_url where is the reserve, NULL for this exchange + * @param amount total amount expected in the purse + * @param balance current balance in the purse (according to the auditor) + * @param flags purse flags + * @param merge_pub merge capability key + * @param reserve_pub reserve the merge affects + * @param merge_sig signature affirming the merge + * @param purse_pub purse key + * @param merge_timestamp when did the merge happen + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseMergeCallback)( + void *cls, + uint64_t rowid, + const char *partner_base_url, + const struct TALER_Amount *amount, + const struct TALER_Amount *balance, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_PurseMergePublicKeyP *merge_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp merge_timestamp); + + +/** + * 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 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_PurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *purse_value); + + +/** + * 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 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_AllPurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + bool refunded); + + +/** + * Function called with details about purse refunds that have been made, with + * the goal of auditing the purse refund's execution. + * + * @param cls closure + * @param rowid row of the refund event + * @param amount_with_fee amount of the deposit into the purse + * @param coin_pub coin that is to be refunded the @a given amount_with_fee + * @param denom_pub denomination of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRefundCoinCallback)( + void *cls, + uint64_t rowid, + const struct TALER_Amount *amount_with_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** * Function called with details about coins that were melted, * with the goal of auditing the refresh's execution. * @@ -1753,70 +2934,52 @@ struct TALER_EXCHANGEDB_CsRevealFreshCoinData /** - * Types of operations that require KYC checks. + * Generic KYC status for some operation. */ -enum TALER_EXCHANGEDB_KycType +struct TALER_EXCHANGEDB_KycStatus { - /** - * It is unclear for which type of KYC operation - * this information is. + * Number that identifies the KYC requirement the operation + * was about. */ - TALER_EXCHANGEDB_KYC_UNKNOWN = 0, + uint64_t requirement_row; /** - * KYC to be applied for simple withdraws without - * the involvement of wallet-to-wallet payments. - * Tied to the payto:// of the debited account. + * True if the KYC status is "satisfied". */ - TALER_EXCHANGEDB_KYC_WITHDRAW = 1, + bool ok; - /** - * KYC to be applied for simple deposits to a - * merchant's bank account. Tied to the payto:// - * of the credited account. - */ - TALER_EXCHANGEDB_KYC_DEPOSIT = 2, +}; - /** - * KYC that is self-applied by a wallet that is exceeding the amount - * threshold. Tied to the reserve-account public key that identifies the - * funds-holding wallet. - */ - TALER_EXCHANGEDB_KYC_BALANCE = 3, - /** - * KYC that is triggered upon wallet-to-wallet - * payments for the recipient of funds. Tied to the - * reserve public key that identifies the receiving - * wallet. - */ - TALER_EXCHANGEDB_KYC_W2W = 4 +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; }; /** - * Generic KYC status for some operation. + * Function called on each @a amount that was found to + * be relevant for a KYC check. + * + * @param cls closure to allow the KYC module to + * total up amounts and evaluate rules + * @param amount encountered transaction amount + * @param date when was the amount encountered + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to abort iteration + * #GNUNET_SYSERR on internal error (also abort itaration) */ -struct TALER_EXCHANGEDB_KycStatus -{ - /** - * Number that identifies the KYC target the operation - * was about. - */ - uint64_t payment_target_uuid; - - /** - * What kind of KYC operation is this? - */ - enum TALER_EXCHANGEDB_KycType type; - - /** - * True if the KYC status is "satisfied". - */ - bool ok; - -}; +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_KycAmountCallback)( + void *cls, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute date); /** @@ -1845,6 +3008,7 @@ typedef void * @param merchant_sig signature of the merchant * @param h_contract_terms hash of the proposal data known to merchant and customer * @param rtransaction_id refund transaction ID chosen by the merchant + * @param full_refund true if the refunds total up to the entire value of the deposit * @param amount_with_fee amount that was deposited including fee * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ @@ -1858,6 +3022,7 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_MerchantSignatureP *merchant_sig, const struct TALER_PrivateContractHashP *h_contract_terms, uint64_t rtransaction_id, + bool full_refund, const struct TALER_Amount *amount_with_fee); @@ -1889,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); /** @@ -1924,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) @@ -1937,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, @@ -2039,6 +3212,26 @@ typedef enum GNUNET_GenericReturnValue /** + * Function called on transient aggregations matching + * a particular hash of a payto URI. + * + * @param cls + * @param payto_uri corresponding payto URI + * @param wtid wire transfer identifier of transient aggregation + * @param merchant_pub public key of the merchant + * @param total amount aggregated so far + * @return true to continue iterating + */ +typedef bool +(*TALER_EXCHANGEDB_TransientAggregationCallback)( + void *cls, + const char *payto_uri, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_Amount *total); + + +/** * Callback with data about a prepared wire transfer. * * @param cls closure @@ -2082,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); /** @@ -2112,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); /** @@ -2127,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 @@ -2138,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); /** @@ -2161,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); /** @@ -2190,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); /** @@ -2235,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. */ @@ -2263,63 +3571,20 @@ struct TALER_EXCHANGEDB_Plugin (*drop_tables)(void *cls); /** - * Drop the Taler tables on a shard. This should only be used in testcases. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param old_idx the index which was used then the database was initialized. - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ - enum GNUNET_GenericReturnValue - (*drop_shard_tables)(void *cls, - uint32_t old_idx); - - /** * 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); - - /** - * 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); + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); - /** - * 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. @@ -2346,6 +3611,18 @@ struct TALER_EXCHANGEDB_Plugin (*start_read_committed)(void *cls, const char *name); + /** + * Start a READ ONLY serializable transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param name unique name identifying the transaction (for debugging) + * must point to a constant + * @return #GNUNET_OK on success + */ + enum GNUNET_GenericReturnValue + (*start_read_only)(void *cls, + const char *name); + /** * Commit a transaction. @@ -2543,79 +3820,58 @@ struct TALER_EXCHANGEDB_Plugin * @param[in,out] reserve the reserve data. The public key of the reserve should be set * in this structure; it is used to query the database. The balance * and expiration are then filled accordingly. - * @param[out] kyc set to the KYC status of the reserve * @return transaction status */ enum GNUNET_DB_QueryStatus (*reserves_get)(void *cls, - struct TALER_EXCHANGEDB_Reserve *reserve, - struct TALER_EXCHANGEDB_KycStatus *kyc); + struct TALER_EXCHANGEDB_Reserve *reserve); /** - * Set the KYC status to "OK" for a bank account. + * Get the origin of funds of a reserve. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param h_payto which account has been checked - * @param id ID data to persist - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*set_kyc_ok)(void *cls, - const struct TALER_PaytoHashP *h_payto, - const char *id); - - - /** - * Get the @a kyc status and @a h_payto by UUID. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param h_payto set to the hash of the account's payto URI (unsalted) - * @param[out] kyc set to the KYC status of the account + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] h_payto set to hash of the wire source payto://-URI * @return transaction status */ enum GNUNET_DB_QueryStatus - (*select_kyc_status)(void *cls, - const struct TALER_PaytoHashP *h_payto, - struct TALER_EXCHANGEDB_KycStatus *kyc); + (*reserves_get_origin)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_PaytoHashP *h_payto); /** - * Get the KYC status for a wallet. If the status is unknown, - * inserts a new status record (hence INsertSELECT). + * Extract next KYC alert. Deletes the alert. * * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the wallet - * @param[out] kyc set to the KYC status of the wallet + * @param trigger_type which type of alert to drain + * @param[out] h_payto set to hash of payto-URI where KYC status changed * @return transaction status */ enum GNUNET_DB_QueryStatus - (*inselect_wallet_kyc_status)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_EXCHANGEDB_KycStatus *kyc); + (*drain_kyc_alert)(void *cls, + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto); /** - * 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); /** @@ -2629,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); @@ -2648,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] kyc set to the KYC status of the reserve - * @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, - struct TALER_EXCHANGEDB_KycStatus *kyc_ok, - uint64_t *ruuid); - /** * Perform reserve update as part of a batch withdraw operation, checking @@ -2686,9 +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] kyc set to the KYC status of the reserve + * @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 */ @@ -2698,9 +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_EXCHANGEDB_KycStatus *kyc_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, uint64_t *ruuid); @@ -2721,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, @@ -2729,25 +3975,85 @@ 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); /** - * Check that reserve remains below threshold for KYC - * checks after withdraw operation. + * 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 ruuid identifies the reserve to check - * @param withdraw_start starting point to accumulate from - * @param upper_limit maximum amount allowed - * @param[out] below_limit set to true if the limit was not exceeded + * @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_withdraw_limit_check)( + (*do_age_withdraw)( void *cls, - uint64_t ruuid, - struct GNUNET_TIME_Absolute withdraw_start, - const struct TALER_Amount *upper_limit, - bool *below_limit); + 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); /** @@ -2755,25 +4061,22 @@ struct TALER_EXCHANGEDB_Plugin * 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); /** @@ -2800,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 @@ -2815,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); @@ -2868,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, @@ -2898,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, @@ -2908,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 @@ -2920,28 +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 set to the reserve balance - * @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, - 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 @@ -3016,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, @@ -3028,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 @@ -3039,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. @@ -3057,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 @@ -3085,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. * @@ -3124,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); /** @@ -3141,8 +4501,6 @@ struct TALER_EXCHANGEDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param start_shard_row minimum shard row to select * @param end_shard_row maximum shard row to select (inclusive) - * @param kyc_off true if we should not check the KYC status because - * this exchange does not need/support KYC checks. * @param[out] merchant_pub set to the public key of a merchant with a ready deposit * @param[out] payto_uri set to the account of the merchant, to be freed by caller * @return transaction status code @@ -3151,18 +4509,10 @@ struct TALER_EXCHANGEDB_Plugin (*get_ready_deposit)(void *cls, uint64_t start_shard_row, uint64_t end_shard_row, - bool kyc_off, struct TALER_MerchantPublicKeyP *merchant_pub, 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. @@ -3189,7 +4539,9 @@ 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 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 */ @@ -3198,15 +4550,18 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_PaytoHashP *h_payto, 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); /** - * Find existing entry in the transient aggregation table. + * Select existing entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant * @param exchange_account_section exchange account to use * @param[out] wtid set to the raw wire transfer identifier to be used * @param[out] total existing amount to be wired in the future @@ -3216,18 +4571,37 @@ struct TALER_EXCHANGEDB_Plugin (*select_aggregation_transient)( void *cls, const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, const char *exchange_account_section, struct TALER_WireTransferIdentifierRawP *wtid, struct TALER_Amount *total); /** + * Find existing entry in the transient aggregation table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param cb function to call on each matching entry + * @param cb_cls closure for @a cb + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*find_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_TransientAggregationCallback cb, + void *cb_cls); + + + /** * Update existing entry in the transient aggregation table. * @a h_payto is only needed for query performance. * * @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 */ @@ -3236,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); @@ -3335,20 +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 include_recoup include recoup transactions of the coin? - * @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, - int include_recoup, - 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); /** @@ -3397,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 @@ -3411,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); /** @@ -3453,11 +4830,10 @@ struct TALER_EXCHANGEDB_Plugin * Insert global fee set into database. * * @param cls closure - * @param start_date when does the fee go into effect - * @param end_date when does the fee end being valid + * @param start_date when does the fees go into effect + * @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 @@ -3469,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, @@ -3507,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 @@ -3520,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); @@ -3544,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 @@ -3553,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 @@ -3560,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); /** @@ -3682,10 +5204,138 @@ 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 + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseDepositCallback cb, + void *cb_cls); + + + /** + * Select account merges above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_account_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AccountMergeCallback cb, + void *cb_cls); + + + /** + * Select purse merges deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseMergeCallback cb, + void *cb_cls); + + + /** + * 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_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select all 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 cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_all_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AllPurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select coins deposited into a purse. + * + * @param cls closure + * @param purse_pub public key of the purse + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_by_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls); + /** * Select refresh sessions above @a serial_id in monotonically increasing @@ -3790,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); /** @@ -3849,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) @@ -3859,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, @@ -3877,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); /** @@ -3894,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); /** @@ -3935,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); /** @@ -3963,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); /** @@ -3979,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); /** @@ -3997,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); /** @@ -4017,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); /** @@ -4044,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); /** @@ -4062,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); @@ -4281,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 @@ -4293,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); @@ -4337,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 @@ -4442,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); /** @@ -4507,24 +6244,18 @@ struct TALER_EXCHANGEDB_Plugin * Function called to persist an encrypted contract associated with a reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param purse_pub the purse the contract is associated with (must exist) - * @param pub_ckey ephemeral key for DH used to encrypt the contract - * @param econtract_size number of bytes in @a econtract * @param econtract the encrypted contract * @param[out] econtract_sig set to the signature over the encrypted contract * @param[out] in_conflict set to true if @a econtract * conflicts with an existing contract; * in this case, the return value will be - * #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_contract)(void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_ContractDiffiePublicP *pub_ckey, - size_t econtract_size, - const void *econtract, - const struct TALER_PurseContractSignatureP *econtract_sig, + const struct TALER_EncryptedContract *econtract, bool *in_conflict); @@ -4548,14 +6279,12 @@ struct TALER_EXCHANGEDB_Plugin size_t *econtract_size, void **econtract); + /** * Function called to retrieve an encrypted contract. * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub key to lookup the contract by - * @param[out] pub_ckey set to the ephemeral DH used to encrypt the contract - * @param[out] econtract_sig set to the signature over the encrypted contract - * @param[out] econtract_size set to the number of bytes in @a econtract * @param[out] econtract set to the encrypted contract on success, to be freed by the caller * @return transaction status code */ @@ -4563,10 +6292,7 @@ struct TALER_EXCHANGEDB_Plugin (*select_contract_by_purse)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_ContractDiffiePublicP *pub_ckey, - struct TALER_PurseContractSignatureP *econtract_sig, - size_t *econtract_size, - void **econtract); + struct TALER_EncryptedContract *econtract); /** @@ -4585,7 +6311,7 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] in_conflict set to true if the meta data * conflicts with an existing purse; * in this case, the return value will be - * #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -4623,26 +6349,32 @@ 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); /** - * Function called to reutrn meta data about a purse by the + * Function called to return meta data about a purse by the * purse public key. * * @param cls the @e cls of this struct with the plugin-specific state @@ -4657,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, @@ -4714,7 +6446,8 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] balance_ok set to false if the coin's * remaining balance is below @a amount; * in this case, the return value will be - * #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure + * #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 @@ -4728,10 +6461,49 @@ 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. + * + * @param cls closure + * @param purse_pub public key of a purse + * @param balance new balance to store under the purse + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*set_purse_balance)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); + + + /** * Function called to obtain a coin deposit data from * depositing the coin into a purse. * @@ -4739,6 +6511,8 @@ struct TALER_EXCHANGEDB_Plugin * @param purse_pub purse to credit * @param coin_pub coin to deposit (debit) * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] h_denom_pub set to hash of denomination of the coin + * @param[out] phac set to hash of age restriction on the coin * @param[out] coin_sig set to signature affirming the operation * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller * @return transaction status code @@ -4749,6 +6523,8 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, struct TALER_CoinSpendSignatureP *coin_sig, char **partner_url); @@ -4767,6 +6543,7 @@ struct TALER_EXCHANGEDB_Plugin * @param reserve_pub public key of the reserve to credit * @param[out] no_partner set to true if @a partner_url is unknown * @param[out] no_balance set to true if the @a purse_pub is not paid up yet + * @param[out] no_reserve set to true if the @a reserve_pub is not known * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already * @return transaction status code */ @@ -4797,6 +6574,7 @@ struct TALER_EXCHANGEDB_Plugin * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota * @param reserve_pub public key of the reserve to credit * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse * @return transaction status code */ @@ -4810,6 +6588,7 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_Amount *purse_fee, const struct TALER_ReservePublicKeyP *reserve_pub, bool *in_conflict, + bool *no_reserve, bool *insufficient_funds); @@ -4823,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 @@ -4832,64 +6612,632 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_PurseMergeSignatureP *merge_sig, struct GNUNET_TIME_Timestamp *merge_timestamp, char **partner_url, - struct TALER_ReservePublicKeyP *reserve_pub); + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded); /** - * Function called to approve merging of a purse with - * an account, made by the receiving account. + * Function called to initiate closure of an account. + * + * @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 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, + const struct TALER_Amount *balance, + const struct TALER_Amount *closing_fee); + + + /** + * Function called to persist a request to drain profits. * * @param cls the @e cls of this struct with the plugin-specific state - * @param purse_pub public key of the purse being merged - * @param reserve_pub public key of the account being credited - * @param reserve_sig signature of the account holder affirming the merge + * @param wtid wire transfer ID to use + * @param account_section account to drain + * @param payto_uri account to wire funds to + * @param request_timestamp time of the signature + * @param amount amount to wire + * @param master_sig signature affirming the operation * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*do_account_merge)( + (*insert_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + const char *account_section, + const char *payto_uri, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *amount, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Function called to get information about a profit drain event. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wtid wire transfer ID to look up drain event for + * @param[out] serial set to serial ID of the entry + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t *serial, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); + + + /** + * Get profit drain operation ready to execute. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param[out] serial set to serial ID of the entry + * @param[out] wtid set set to wire transfer ID to use + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*profit_drains_get_pending)( void *cls, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig); + uint64_t *serial, + struct TALER_WireTransferIdentifierRawP *wtid, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); /** - * 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). + * Set profit drain operation to finished. * * @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 serial serial ID of the entry to mark finished * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_history_request)( + (*profit_drains_set_finished)( + void *cls, + uint64_t serial); + + + /** + * Insert KYC requirement for @a h_payto account into table. + * + * @param cls closure + * @param requirements requirements that must be checked + * @param h_payto account that must be KYC'ed + * @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 *requirements, + const struct TALER_PaytoHashP *h_payto, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Absolute request_timestamp, - const struct TALER_Amount *history_fee); + uint64_t *requirement_row); /** - * Function called to initiate closure of an account. + * Begin KYC requirement process. + * + * @param cls closure + * @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_process_by_row)( + void *cls, + 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 requirement. + * + * @param cls closure + * @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 + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_kyc_requirement_by_row)( + void *cls, + uint64_t requirement_row, + char **requirements, + enum TALER_AmlDecisionState *aml_status, + struct TALER_PaytoHashP *h_payto); + + + /** + * 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] 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_process_by_account)( + void *cls, + const char *provider_section, + const struct TALER_PaytoHashP *h_payto, + uint64_t *process_row, + struct GNUNET_TIME_Absolute *expiration, + char **provider_account_id, + char **provider_legitimization_id); + + + /** + * Lookup an + * @a h_payto by @a provider_legitimization_id. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @param[out] process_row identifies the legitimization process on our end + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*kyc_provider_account_lookup)( + void *cls, + const char *provider_section, + const char *provider_legitimization_id, + struct TALER_PaytoHashP *h_payto, + uint64_t *process_row); + + + /** + * Call us on KYC processes satisfied for the given + * account. * * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the account to close - * @param reserve_sig signature affiming that the account is to be closed - * @param[out] final_balance set to the final balance in the account that will be wired back to the origin account + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_close_request)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig, - struct TALER_Amount *final_balance); + (*select_satisfied_kyc_processes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_SatisfiedProviderCallback spc, + void *spc_cls); + + + /** + * 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. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @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 + (*select_withdraw_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on aggregated amounts after @a time_limit which are relevant for a + * KYC trigger for a the (credited) account identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @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 + (*select_aggregation_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on merged reserve amounts after @a time_limit which are relevant for a + * KYC trigger for a the wallet identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @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 + (*select_merge_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + 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); }; |