diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 117 | ||||
-rw-r--r-- | src/include/taler_extensions.h | 201 | ||||
-rw-r--r-- | src/include/taler_extensions_policy.h | 199 |
3 files changed, 294 insertions, 223 deletions
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 80a19b67..881e0cef 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -26,6 +26,7 @@ #include <gnunet/gnunet_db_lib.h> #include "taler_json_lib.h" #include "taler_signatures.h" +#include "taler_extensions_policy.h" /** @@ -223,7 +224,6 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_EXTENSIONS, TALER_EXCHANGEDB_RT_POLICY_DETAILS, TALER_EXCHANGEDB_RT_POLICY_FULFILMENTS, - TALER_EXCHANGEDB_RT_POLICY_DETAILS_FULFILMENTS, TALER_EXCHANGEDB_RT_PURSE_REQUESTS, TALER_EXCHANGEDB_RT_PURSE_REFUNDS, TALER_EXCHANGEDB_RT_PURSE_MERGES, @@ -528,24 +528,27 @@ struct TALER_EXCHANGEDB_TableData struct { - char *policy_options; - struct GNUNET_HashCode serial_id; + struct GNUNET_HashCode hash_code; + json_t *policy_json; + bool no_policy_json; struct GNUNET_TIME_Timestamp deadline; - uint16_t timeout_fulfilment_state; - uint16_t fulfilment_state; + 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_HashCode serial_id; - uint64_t fulfilment_id; - } policy_details_fulfilments; - - struct - { - char *fulfilment_proof; - struct GNUNET_TIME_Timestamp fulfilment_timestamp; - } policy_fulfilments; + 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 { @@ -889,7 +892,6 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData struct TALER_AgeMask age_mask; }; - /** * Signature of a function called with information about the exchange's * denomination keys. @@ -1446,36 +1448,28 @@ struct TALER_EXCHANGEDB_Deposit char *receiver_wire_account; /** - * Additional details for a policy relevant for this - * deposit operation, possibly NULL! + * Additional policy and its options, relevant for this deposit operation, + * possibly NULL! */ - json_t *policy_details; - bool has_policy_details; + json_t *policy_json; - /** - * If policy_details are present, the corresponding policy extension - * calculates a serial id under which the policy_details shall be stored in - * the policy_details table. + /* + * True if @e policy_json was provided */ - struct GNUNET_HashCode policy_serial_id; + bool has_policy; /** - * If policy_details are present, the corresponding policy extension can set - * a deadline for this policy. Can be "forever". + * Hash over the @e policy_options. Only filled if @e has_policy is true. + * Needed for the verification of the deposit's signature */ - struct GNUNET_TIME_Timestamp policy_deadline; - - /** - * The state that a _pending_ policy should be put into once the timeout triggers - */ - uint16_t policy_state_on_timeout; - + struct TALER_ExtensionPolicyHashP h_policy; /** - * Hash over the @e policy_details. Only filled if has_policy_details is - * true. + * If @e policy_json was present, the corresponding policy extension + * calculates these details. These will be persisted in the policy_details + * table. */ - struct TALER_ExtensionPolicyHashP h_policy; + struct TALER_PolicyDetails policy_details; /** * Time when this request was generated. Used, for example, to @@ -1549,8 +1543,8 @@ struct TALER_EXCHANGEDB_DepositListEntry struct TALER_PrivateContractHashP h_contract_terms; /** - * Hash over the poliy data for this deposit - * (remains unknown to the Exchange). + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature */ struct TALER_ExtensionPolicyHashP h_policy; @@ -3342,6 +3336,39 @@ struct TALER_EXCHANGEDB_Plugin bool *conflict, bool *nonce_reuse); + /** + * Retrieve the details to a policy given by its hash_code + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param hc Hash code that identifies the policy + * @param[out] detail retrieved policy details + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*get_policy_details)( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *detail); + + /** + * Persist the policy details that extends a deposit. The particular policy + * - referenced by details->hash_code - might already exist in the table, in + * which case the call will update the contents of the record with @e details + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param details The parsed `struct TALER_PolicyDetails` according to the responsible policy extension. + * @param[out] policy_details_serial_id The ID of the entry in the policy_details table + * @param[out] accumulated_total The total amount accumulated in that policy + * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*persist_policy_details)( + void *cls, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state); /** * Perform deposit operation, checking for sufficient balance @@ -3351,6 +3378,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 policy_details_serial_id (pointer to) the row ID of the policy details, maybe NULL * @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 @@ -3362,6 +3390,7 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_EXCHANGEDB_Deposit *deposit, uint64_t known_coin_id, const struct TALER_PaytoHashP *h_payto, + uint64_t *policy_details_serial_id, struct GNUNET_TIME_Timestamp *exchange_timestamp, bool *balance_ok, bool *in_conflict); @@ -3389,6 +3418,18 @@ struct TALER_EXCHANGEDB_Plugin bool *zombie_required, bool *balance_ok); + /** + * 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 diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h index 5a5841e5..24e0366d 100644 --- a/src/include/taler_extensions.h +++ b/src/include/taler_extensions.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2022 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 @@ -25,7 +25,7 @@ #include "taler_crypto_lib.h" #include "taler_json_lib.h" #include "taler_mhd_lib.h" -#include "taler_exchangedb_plugin.h" +#include "taler_extensions_policy.h" #define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-" @@ -54,8 +54,8 @@ struct TALER_Extensions }; /* Forward declarations */ -enum TALER_PolicyFulfilmentState; -struct TALER_PolicyFulfilmentOutcome; +enum TALER_PolicyFulfillmentState; +struct TALER_PolicyFulfillmentOutcome; /* * @brief Represents the implementation of an extension. @@ -165,31 +165,23 @@ struct TALER_Extension */ /** - * @brief Handler to check a policy. Can be NULL; + * @brief Handler to check an incoming policy and create a + * TALER_PolicyDetails. Can be NULL; * * When a deposit request refers to this extension in its policy * (see https://docs.taler.net/core/api-exchange.html#deposit), this handler * will be called before the deposit transaction. * - * @param[in] policy_details Details about the policy, provided by the client + * @param[in] policy_json Details about the policy, provided by the client * during a deposit request. - * @param[out] serial On success, will contain the serial-ID under which the - * exchange should save the policy_details in the deposit table. - * @param[out] deadline On success, set to the deadline until the policy must - * be fulfilled. Might be "forever". This value is used by an - * external mechanism to detect timeouts. - * @param[out] state_on_timeout On GNUNET_OK, which state shall the - * fulfilment of this policy be put in. MUST be either - * TALER_PolicyFulfilmentTimeoutTransfer or - * TALER_PolicyFulfilmentTimeoutRefreshable + * @param[out] details On success, will contain the details to the policy, + * evaluated by the corresponding policy handler. * @param[out] error_hint On error, will contain a hint * @return GNUNET_OK if the data was accepted by the extension. */ - enum GNUNET_GenericReturnValue (*parse_policy_details)( - const json_t *policy_details, - struct GNUNET_HashCode *serial, - struct GNUNET_TIME_Timestamp *deadline, - enum TALER_PolicyFulfilmentState *state_on_timeout, + enum GNUNET_GenericReturnValue (*create_policy_details)( + const json_t *policy_json, + struct TALER_PolicyDetails *details, const char **error_hint); /** @@ -197,18 +189,16 @@ struct TALER_Extension * * @param[in] root The JSON body from the request * @param[in] args Additional query parameters of the request. - * @param[in] serial_id_check Helper function to check the presence of serial_ids in policy_details. Can be used by the handler to ensure the presence of entries before starting calculations. - * @param[out] outcome Result of the operation. Must be freed via TALER_policy_fulfilment_outcome_free after use. + * @param[in,out] details List of policy details related to the incoming fulfillment proof + * @param[in] details_len Size of the list @e details * @param[out] output JSON output to return to the client * @return GNUNET_OK on success. */ enum GNUNET_GenericReturnValue (*policy_post_handler)( const json_t *root, const char *const args[], - enum GNUNET_GenericReturnValue (*serial_id_check)(struct GNUNET_HashCode - serial_ids[], size_t - size), - struct TALER_PolicyFulfilmentOutcome **outcome, + struct TALER_PolicyDetails *details, + size_t details_len, json_t **output); /** @@ -395,163 +385,4 @@ TALER_extensions_is_age_restriction_enabled (); struct TALER_AgeMask TALER_extensions_get_age_restriction_mask (); - -/* - * =================================== - * Policy extensions related API - * =================================== - */ - - -/* - * @brief Describes the states of fulfilment of a policy bound to a deposit - */ -enum TALER_PolicyFulfilmentState -{ - /* Initial state of the policy */ - TALER_PolicyFulfilmentPending = 0, - - /* - * Policy provably fulfilled. The semantics of the policy require that - * the exchange MUST transfer amount in the associated deposit to the - * payto-URI */ - TALER_PolicyFulfilmentSuccessTransfer = 1, - - /* - * Policy provably fulfilled. The semantics of the policy require that - * the coins' value in the associated deposit remains and the owner can - * refresh them. */ - TALER_PolicyFulfilmentSuccessRefreshable = 2, - - /* - * Policy provably UNfulfilled. The semantics of the policy require - * that the exchange MUST transfer amount in the associated deposit to - * the payto-URI. */ - TALER_PolicyFulfilmentFailureTransfer = 3, - - /* - * Policy provably UNfulfilled. The semantics of the policy require that - * the coins' value in the associated deposit remains and the owner can - * refresh them. */ - TALER_PolicyFulfilmentFailureRefreshable = 4, - - /* - * Policy timed out. The semantics of the policy require that the - * exchange MUST transfer amount in the associated deposit to the - * payto-URI. */ - TALER_PolicyFulfilmentTimeoutTransfer = 5, - - /* - * Policy timed out. The semantics of the policy require that the - * coins' value in the associated deposit remains and the owner can - * refresh them. */ - TALER_PolicyFulfilmentTimeoutRefreshable = 6, - - TALER_PolicyFulfilmentStateMax = TALER_PolicyFulfilmentTimeoutRefreshable -}; - - -const char * -TALER_policy_fulfilment_state_str (enum TALER_PolicyFulfilmentState state); - -/* - * @brief Respresents the outcome of a policy fulfilment evaluation - * returned by a http_post_handler. - */ -struct TALER_PolicyFulfilmentOutcome -{ - size_t len; - struct TALER_PolicyFulfilmentOutcomePosition - { - /* Identifies the particular policy in the policy_details */ - struct GNUNET_HashCode serial_id; - - /* The state that the policy should be be put into. */ - enum TALER_PolicyFulfilmentState state; - - /* If @e has_new_amount is true, the actual amount to be transfered - * according to the @e state is not taken from the associated deposit - * entry, but provided with @new_amount - */ - bool has_new_amount; - struct TALER_Amount new_amount; - - } *positions; -}; - - -/* - * @brief allocate a TALER_PolicyFulfilmentOutcome - */ -struct TALER_PolicyFulfilmentOutcome * -TALER_policy_fulfilment_outcome_new (size_t len); - -/* - * @brief free the content of a TALER_PolicyFulfilmentOutcome - */ -void -TALER_policy_fulfilment_outcome_free ( - struct TALER_PolicyFulfilmentOutcome *outcome); - - -/* - * @brief Extracts meta information from policy_details - * - * @param[in] policy_details JSON of the policy detail from a deposit request - * @param[out] serial On GNUNET_OK, the hash code that should be used to save the policy_details in the policy_details table - * @param[out] deadline On GNUNET_OK, the deadline that should be saved in the policy_details table - * @param[out] state_on_timeout On GNUNET_OK, which state shall the fulfilment of this policy be put in - * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed - * @return GNUNET_OK on success, with *extension set to the correct extension. - * GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was - * invalid, with *error_hint maybe non-NULL. - */ -enum GNUNET_GenericReturnValue -TALER_extensions_extract_meta_data_from_policy_details ( - const json_t *policy_details, - struct GNUNET_HashCode *serial, - struct GNUNET_TIME_Timestamp *deadline, - enum TALER_PolicyFulfilmentState *state_on_timeout, - const char **error_hint); - - -/* - * ================================ - * Merchant refund policy - * ================================ - */ -struct TALER_ExtensionPolicyMerchantRefundPolicyConfig -{ - struct GNUNET_TIME_Relative max_timeout; -}; - -/* - * ================================ - * Brandt-Vickrey Auctions policy - * ================================ - */ -/* - * @brief Configuration for Brandt-Vickrey auctions policy - */ -struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig -{ - uint16_t max_bidders; - uint16_t max_prices; - struct TALER_Amount auction_fee; -}; - - -/* - * ================================ - * Escrowed Payments policy - * ================================ - */ -/* - * @brief Configuration for escrowed payments policy - */ -struct TALER_ExtensionPolicyEscrowedPaymentsConfig -{ - struct GNUNET_TIME_Relative max_timeout; -}; - #endif diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h new file mode 100644 index 00000000..cd75f2d4 --- /dev/null +++ b/src/include/taler_extensions_policy.h @@ -0,0 +1,199 @@ +/* + This file is part of TALER + Copyright (C) 2022 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file include/taler_extensions_policy.h + * @brief Interface for policy extensions + * @author Özgür Kesim + */ +#ifndef TALER_EXTENSIONS_POLICY_H +#define TALER_EXTENSIONS_POLICY_H + +#include <gnunet/gnunet_util_lib.h> +#include "taler_crypto_lib.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" + +/* + * @brief Describes the states of fulfillment of a policy bound to a deposit + */ +enum TALER_PolicyFulfillmentState +{ + /* General error state of an fulfillment. */ + TALER_PolicyFulfillmentFailure = 0, + + /* The policy is not yet ready due to insufficient funding. More deposits are + * necessary for it to become ready . */ + TALER_PolicyFulfillmentInsufficient = 1, + + /* The policy is funded and ready, pending */ + TALER_PolicyFulfillmentReady = 2, + + /* Policy is provably fulfilled. */ + TALER_PolicyFulfillmentSuccess = 3, + + /* Policy fulfillment has timed out */ + TALER_PolicyFulfillmentTimeout = 4, + + TALER_PolicyFulfillmentStateCount = TALER_PolicyFulfillmentTimeout + 1 +}; + + +/* + * @brief Returns a string representation of the state of a policy fulfillment + */ +const char * +TALER_policy_fulfillment_state_str (enum TALER_PolicyFulfillmentState state); + + +/* @brief Details of a policy for a deposit request */ +struct TALER_PolicyDetails +{ + /* Hash code that should be used for the .policy_hash_code field when + * this policy is saved in the policy_details table. */ + struct GNUNET_HashCode hash_code; + + /* Content of the policy in its original JSON form */ + const json_t *policy_json; + + /* When the deadline is meat and the policy is still in "Ready" state, + * a timeout-handler will transfer the amount + * (total_amount - policy_fee - refreshable_amount) + * to the payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins */ + struct GNUNET_TIME_Timestamp deadline; + + /* The amount to which this policy commits to. It must be at least as + * large as @e policy_fee. */ + struct TALER_Amount commitment; + + /* The total sum of contributions from coins so far to fund this + * policy. It must be at least as large as @commitment in order to be + * sufficiently funded. */ + struct TALER_Amount accumulated_total; + + /* The fee from the exchange for handling the policy. It is due when + * the state changes to Timeout or Success. */ + struct TALER_Amount policy_fee; + + /* The amount that will be transfered to the payto-URIs from the + * corresponding deposits when the fulfillment state changes to Timeout + * or Success. Note that a fulfillment handler can alter this upon + * arrival of a proof of fulfillment. The remaining amount + * (accumulated_amount - policy_amount - transferable_amount) */ + struct TALER_Amount transferable_amount; + + /* The state of fulfillment of a policy. + * - If the state is Insufficient, the client is required to call + * /deposit -maybe multiple times- with enough coins and the same + * policy details in order to reach the required amount. The state is + * then changed to Ready. + * - If the state changes to Timeout or Success, a handler will transfer + * the amount (total_amount - policy_fee - refreshable_amount) to the + * payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins. */ + enum TALER_PolicyFulfillmentState fulfillment_state; + + /* If there is a proof of fulfillment, the row ID from the + * policy_fulfillment table */ + uint64_t policy_fulfillment_id; + bool no_policy_fulfillment_id; +}; + +/* + * @brief All information required for the database transaction when handling a + * proof of fulfillment request. + */ +struct TALER_PolicyFulfillmentTransactionData +{ + /* The incoming proof, provided by a client */ + const json_t *proof; + + /* The Hash of the proof */ + struct GNUNET_HashCode h_proof; + + /* The timestamp of retrieval of the proof */ + struct GNUNET_TIME_Timestamp timestamp; + + /* The ID of the proof in the policy_fulfillment table. Will be set + * during the transaction. Needed to fill the table + * policy_details_fulfillments. */ + uint64_t fulfillment_id; + + /* The list of policy details. Will be updated by the policy handler */ + struct TALER_PolicyDetails *details; + size_t details_count; +}; + + + +/* + * @brief Extracts policy details from the deposit's policy options and the policy extensions + * + * @param[in] policy_options JSON of the policy options from a deposit request + * @param[out] details On GNUNET_OK, the parsed details + * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed + * @return GNUNET_OK on success, GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was + * invalid, with *error_hint maybe non-NULL. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_create_policy_details ( + const json_t *policy_options, + struct TALER_PolicyDetails *details, + const char **error_hint); + + +/* + * ================================ + * Merchant refund policy + * ================================ + */ +struct TALER_ExtensionPolicyMerchantRefundPolicyConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +/* + * ================================ + * Brandt-Vickrey Auctions policy + * ================================ + */ +/* + * @brief Configuration for Brandt-Vickrey auctions policy + */ +struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig +{ + uint16_t max_bidders; + uint16_t max_prices; + struct TALER_Amount auction_fee; +}; + + +/* + * ================================ + * Escrowed Payments policy + * ================================ + */ +/* + * @brief Configuration for escrowed payments policy + */ +struct TALER_ExtensionPolicyEscrowedPaymentsConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +#endif |