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 | 
