/*
  This file is part of Anastasis
  Copyright (C) 2019-2022 Anastasis SARL

  Anastasis 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.

  Anastasis 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
  Anastasis; see the file COPYING.LIB.  If not, see <http://www.gnu.org/licenses/>
*/
/**
 * @file include/anastasis_service.h
 * @brief C interface of libanastasisrest, a C library to use merchant's HTTP API
 * @author Christian Grothoff
 * @author Dennis Neufeld
 * @author Dominik Meister
 */
#ifndef ANASTASIS_SERVICE_H
#define ANASTASIS_SERVICE_H

#include "anastasis_crypto_lib.h"
#include "anastasis_util_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include <jansson.h>


/**
 * Anastasis authorization method configuration
 */
struct ANASTASIS_AuthorizationMethodConfig
{
  /**
   * Type of the method, i.e. "question".
   */
  const char *type;

  /**
   * Fee charged for accessing key share using this method, in the
   * provider's primary currency.  Kept because a provider speaking
   * protocol version 2 offers nothing else.
   */
  struct TALER_Amount usage_fee;

  /**
   * Fee charged for accessing key share using this method, one entry
   * per currency the provider accepts.  Synthesized from @e usage_fee
   * for a provider that does not offer the plural field yet.  Empty
   * means the method is free.
   */
  struct TALER_AmountList usage_fees;
};


/**
 * @brief Anastasis configuration data.
 */
struct ANASTASIS_Config
{

  /**
   * HTTP status returned.
   */
  unsigned int http_status;

  /**
   * Taler-specific error code, #TALER_EC_NONE on success.
   */
  enum TALER_ErrorCode ec;

  /**
   * Full response in JSON, if provided.
   */
  const json_t *response;

  /**
   * Details depending on @e http_status.
   */
  union
  {

    /**
     * Details on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Protocol version supported by the server.
       */
      const char *version;

      /**
       * Business name of the anastasis provider.
       */
      const char *business_name;

      /**
       * Array of authorization methods supported by the server.
       */
      const struct ANASTASIS_AuthorizationMethodConfig *methods;

      /**
       * Length of the @e methods array.
       */
      unsigned int methods_length;

      /**
       * Maximum size of an upload in megabytes.
       */
      uint32_t storage_limit_in_megabytes;

      /**
       * Currencies the provider prices its service in, primary
       * currency first.  For a provider speaking protocol version 2
       * this is the single currency of @e annual_fee.
       */
      const char **currencies;

      /**
       * Length of the @e currencies array.
       */
      unsigned int currencies_len;

      /**
       * Annual fee for an account / policy upload, in the primary
       * currency.
       */
      struct TALER_Amount annual_fee;

      /**
       * Annual fee for an account / policy upload, per currency.
       * Synthesized from @e annual_fee for a provider speaking
       * protocol version 2.
       */
      struct TALER_AmountList annual_fees;

      /**
       * Fee for a truth upload, in the primary currency.
       */
      struct TALER_Amount truth_upload_fee;

      /**
       * Fee for a truth upload, per currency.
       */
      struct TALER_AmountList truth_upload_fees;

      /**
       * Maximum legal liability for data loss covered by the
       * provider, in the primary currency.
       */
      struct TALER_Amount liability_limit;

      /**
       * Maximum legal liability for data loss covered by the
       * provider, per currency.
       */
      struct TALER_AmountList liability_limits;

      /**
       * Provider salt.
       */
      struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt;
    } ok;

  } details;

};


/**
 * Function called with the result of a /config request.
 * Note that an HTTP status of #MHD_HTTP_OK is no guarantee
 * that @a acfg is non-NULL. @a acfg is non-NULL only if
 * the server provided an acceptable response.
 *
 * @param cls closure
 * @param acfg configuration obtained, NULL if we could not parse it
 */
#ifndef ANASTASIS_CONFIG_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_ConfigCallback.
 */
#define ANASTASIS_CONFIG_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_ConfigCallback)(ANASTASIS_CONFIG_RESULT_CLOSURE *cls,
                            const struct ANASTASIS_Config *acfg);


/**
 * @brief A Config Operation Handle
 */
struct ANASTASIS_ConfigOperation;


/**
 * Run a GET /config request against the Anastasis backend.
 *
 * @param ctx CURL context to use
 * @param base_url base URL of the Anastasis backend
 * @param cb function to call with the results
 * @param cb_cls closure for @a cb
 * @return handle to cancel the operation
 */
struct ANASTASIS_ConfigOperation *
ANASTASIS_get_config (struct GNUNET_CURL_Context *ctx,
                      const char *base_url,
                      ANASTASIS_ConfigCallback cb,
                      ANASTASIS_CONFIG_RESULT_CLOSURE *cb_cls);


/**
 * Cancel ongoing #ANASTASIS_get_config() request.
 *
 * @param co configuration request to cancel.
 */
void
ANASTASIS_config_cancel (struct ANASTASIS_ConfigOperation *co);


/****** POLICY API ******/


/**
 * Detailed meta data result.
 */
struct ANASTASIS_MetaDataEntry
{

  /**
   * Timestamp of the backup at the server.
   */
  struct GNUNET_TIME_Timestamp server_time;

  /**
   * The encrypted meta data we downloaded.
   */
  const void *meta_data;

  /**
   * Number of bytes in @e meta_data.
   */
  size_t meta_data_size;

  /**
   * Policy version this @e meta_data is for.
   */
  uint32_t version;
};


/**
 * Detailed results for meta data download.
 */
struct ANASTASIS_MetaDownloadDetails
{

  /**
   * HTTP status returned.
   */
  unsigned int http_status;

  /**
   * Taler-specific error code, #TALER_EC_NONE on success.
   */
  enum TALER_ErrorCode ec;

  /**
   * Full response in JSON, if provided.
   */
  const json_t *response;

  /**
   * Details depending on @e http_status.
   */
  union
  {

    /**
     * Details on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Version-sorted array of meta data we downloaded.
       */
      const struct ANASTASIS_MetaDataEntry *metas;

      /**
       * Number of entries in @e metas.
       */
      size_t metas_length;

    } ok;

  } details;
};


/**
 * Callback to process a GET /policy/$POL/meta request
 *
 * @param cls closure
 * @param dd the response details
 */
#ifndef ANASTASIS_POLICY_META_LOOKUP_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_PolicyMetaLookupCallback.
 */
#define ANASTASIS_POLICY_META_LOOKUP_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_PolicyMetaLookupCallback) (
  ANASTASIS_POLICY_META_LOOKUP_RESULT_CLOSURE *cls,
  const struct ANASTASIS_MetaDownloadDetails *dd);


/**
 * Does a GET /policy/$POL/meta.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param anastasis_pub public key of the user's account
 * @param max_version maximum version number to fetch
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to the callback
 * @return handle for this operation, NULL upon errors
 */
struct ANASTASIS_PolicyMetaLookupOperation *
ANASTASIS_policy_meta_lookup (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
  uint32_t max_version,
  ANASTASIS_PolicyMetaLookupCallback cb,
  ANASTASIS_POLICY_META_LOOKUP_RESULT_CLOSURE *cb_cls);


/**
 * Cancel a GET /policy/$POL/meta request.
 *
 * @param plo cancel the policy lookup operation
 */
void
ANASTASIS_policy_meta_lookup_cancel (
  struct ANASTASIS_PolicyMetaLookupOperation *plo);


/**
 * Detailed results from the successful download.
 */
struct ANASTASIS_DownloadDetails
{

  /**
   * HTTP status returned.
   */
  unsigned int http_status;

  /**
   * Taler-specific error code, #TALER_EC_NONE on success.
   */
  enum TALER_ErrorCode ec;

  /**
   * Details depending on @e http_status.
   */
  union
  {

    /**
     * Details on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Signature (already verified).
       */
      struct ANASTASIS_AccountSignatureP sig;

      /**
       * Hash over @e policy and @e policy_size.
       */
      struct GNUNET_HashCode curr_policy_hash;

      /**
       * The backup we downloaded.
       */
      const void *policy;

      /**
       * Number of bytes in @e backup.
       */
      size_t policy_size;

      /**
       * Policy version returned by the service.
       */
      uint32_t version;
    } ok;

  } details;

};


/**
 * Handle for a GET /policy operation.
 */
struct ANASTASIS_PolicyLookupOperation;


/**
 * Callback to process a GET /policy request
 *
 * @param cls closure
 * @param dd the response details
 */
#ifndef ANASTASIS_POLICY_LOOKUP_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_PolicyLookupCallback.
 */
#define ANASTASIS_POLICY_LOOKUP_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_PolicyLookupCallback) (ANASTASIS_POLICY_LOOKUP_RESULT_CLOSURE *cls,
                                   const struct ANASTASIS_DownloadDetails *dd);


/**
 * Does a GET /policy.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param anastasis_pub public key of the user's account
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to the callback
 * @return handle for this operation, NULL upon errors
 */
struct ANASTASIS_PolicyLookupOperation *
ANASTASIS_policy_lookup (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
  ANASTASIS_PolicyLookupCallback cb,
  ANASTASIS_POLICY_LOOKUP_RESULT_CLOSURE *cb_cls);


/**
 * Does a GET /policy for a specific version.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param anastasis_pub public key of the user's account
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to the callback
 * @param version version of the policy to be requested
 * @return handle for this operation, NULL upon errors
 */
struct ANASTASIS_PolicyLookupOperation *
ANASTASIS_policy_lookup_version (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
  ANASTASIS_PolicyLookupCallback cb,
  ANASTASIS_POLICY_LOOKUP_RESULT_CLOSURE *cb_cls,
  unsigned int version);


/**
 * Cancel a GET /policy request.
 *
 * @param plo cancel the policy lookup operation
 */
void
ANASTASIS_policy_lookup_cancel (
  struct ANASTASIS_PolicyLookupOperation *plo);


/**
 * Handle for a POST /policy operation.
 */
struct ANASTASIS_PolicyStoreOperation;


/**
 * High-level ways how an upload may conclude.
 */
enum ANASTASIS_UploadStatus
{
  /**
   * Backup was successfully made.
   */
  ANASTASIS_US_SUCCESS = 0,

  /**
   * Account expired or payment was explicitly requested
   * by the client.
   */
  ANASTASIS_US_PAYMENT_REQUIRED,

  /**
   * HTTP interaction failed, see HTTP status.
   */
  ANASTASIS_US_HTTP_ERROR,

  /**
   * We had an internal error (not sure this can happen,
   * but reserved for HTTP 400 status codes).
   */
  ANASTASIS_US_CLIENT_ERROR,

  /**
   * Server had an internal error.
   */
  ANASTASIS_US_SERVER_ERROR,

  /**
   * Truth already exists. Not applicable for policy uploads.
   */
  ANASTASIS_US_CONFLICTING_TRUTH
};


/**
 * Result of an upload.
 */
struct ANASTASIS_UploadDetails
{
  /**
   * High level status of the upload operation. Determines @e details.
   */
  enum ANASTASIS_UploadStatus us;

  /**
   * HTTP status code.
   */
  unsigned int http_status;

  /**
   * Taler error code.
   */
  enum TALER_ErrorCode ec;

  union
  {

    struct
    {
      /**
       * Hash of the stored recovery data, returned if
       * @e us is #ANASTASIS_US_SUCCESS.
       */
      const struct GNUNET_HashCode *curr_backup_hash;

      /**
       * At what time is the provider set to forget this
       * policy (because the account expires)?
       */
      struct GNUNET_TIME_Timestamp policy_expiration;

      /**
       * Version number of the resulting policy.
       */
      unsigned long long policy_version;

    } success;

    /**
     * Details about required payment.
     */
    struct
    {
      /**
       * A taler://pay/-URI with a request to pay the annual fee for
       * the service.  Returned if @e us is #ANASTASIS_US_PAYMENT_REQUIRED.
       */
      const char *payment_request;

      /**
       * The payment secret (aka order ID) extracted from the @e payment_request.
       */
      struct ANASTASIS_PaymentSecretP ps;
    } payment;

  } details;
};


/**
 * Callback to process a POST /policy request
 *
 * @param cls closure
 * @param up the decoded response body
 */
#ifndef ANASTASIS_POLICY_STORE_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_PolicyStoreCallback.
 */
#define ANASTASIS_POLICY_STORE_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_PolicyStoreCallback) (ANASTASIS_POLICY_STORE_RESULT_CLOSURE *cls,
                                  const struct ANASTASIS_UploadDetails *up);


/**
 * Store policies, does a POST /policy/$ACCOUNT_PUB
 *
 * @param ctx the CURL context used to connect to the backend
 * @param backend_url backend's base URL, including final "/"
 * @param anastasis_priv private key of the user's account
 * @param recovery_data policy data to be stored
 * @param recovery_data_size number of bytes in @a recovery_data
 * @param recovery_meta_data policy meta data to be stored
 * @param recovery_meta_data_size number of bytes in @a recovery_meta_data
 * @param payment_years_requested for how many years would the client like the service to store the truth?
 * @param payment_secret payment identifier of last payment
 * @param payment_timeout how long to wait for the payment, use
 *           #GNUNET_TIME_UNIT_ZERO to let the server pick
 * @param cb callback processing the response from /policy
 * @param cb_cls closure for @a cb
 * @return handle for the operation
 */
struct ANASTASIS_PolicyStoreOperation *
ANASTASIS_policy_store (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *anastasis_priv,
  const void *recovery_data,
  size_t recovery_data_size,
  const void *recovery_meta_data,
  size_t recovery_meta_data_size,
  uint32_t payment_years_requested,
  const struct ANASTASIS_PaymentSecretP *payment_secret,
  struct GNUNET_TIME_Relative payment_timeout,
  ANASTASIS_PolicyStoreCallback cb,
  ANASTASIS_POLICY_STORE_RESULT_CLOSURE *cb_cls);


/**
 * Cancel a POST /policy request.
 *
 * @param pso the policy store operation to cancel
 */
void
ANASTASIS_policy_store_cancel (
  struct ANASTASIS_PolicyStoreOperation *pso);


/****** TRUTH API ******/


/**
 * Handle for a POST /truth operation.
 */
struct ANASTASIS_TruthStoreOperation;


/**
 * Callback to process a POST /truth request
 *
 * @param cls closure
 * @param obj the response body
 */
#ifndef ANASTASIS_TRUTH_STORE_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_TruthStoreCallback.
 */
#define ANASTASIS_TRUTH_STORE_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_TruthStoreCallback) (ANASTASIS_TRUTH_STORE_RESULT_CLOSURE *cls,
                                 const struct ANASTASIS_UploadDetails *up);


/**
 * Store Truth, does a POST /truth/$UUID
 *
 * @param ctx the CURL context used to connect to the backend
 * @param backend_url backend's base URL, including final "/"
 * @param uuid unique identification of the Truth Upload
 * @param type type of the authorization method
 * @param encrypted_keyshare key material to return to the client upon authorization
 * @param truth_mime mime type of @e encrypted_truth (after decryption)
 * @param encrypted_truth_size number of bytes in @e encrypted_truth
 * @param encrypted_truth contains the @a type-specific authorization data
 * @param payment_years_requested for how many years would the client like the service to store the truth?
 * @param payment_timeout how long to wait for the payment, use
 *           #GNUNET_TIME_UNIT_ZERO to let the server pick
 * @param cb callback processing the response from /truth
 * @param cb_cls closure for cb
 * @return handle for the operation
 */
struct ANASTASIS_TruthStoreOperation *
ANASTASIS_truth_store (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
  const char *type,
  const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *encrypted_keyshare,
  const char *truth_mime,
  size_t encrypted_truth_size,
  const void *encrypted_truth,
  uint32_t payment_years_requested,
  struct GNUNET_TIME_Relative payment_timeout,
  ANASTASIS_TruthStoreCallback cb,
  ANASTASIS_TRUTH_STORE_RESULT_CLOSURE *cb_cls);


/**
 * Cancel a POST /truth request.
 *
 * @param tso the truth store operation
 */
void
ANASTASIS_truth_store_cancel (
  struct ANASTASIS_TruthStoreOperation *tso);


/**
 * Possible ways how to proceed with a challenge.
 */
enum ANASTASIS_ChallengeDetailType
{

  /**
   * A challenge TAN was written to a file.
   * The name of the file is provided.
   */
  ANASTASIS_CS_FILE_WRITTEN,

  /**
   * A challenge TAN was sent to the customer.
   * A hint may be provided as to the address used.
   */
  ANASTASIS_CS_TAN_SENT,

  /**
   * A challenge TAN was already recently sent to the customer.
   * A hint may be provided as to the address used.
   */
  ANASTASIS_CS_TAN_ALREADY_SENT,

  /**
   * The customer should wire funds to the bank
   * account address provided.
   */
  ANASTASIS_CS_WIRE_FUNDS

};


/**
 * This structure contains information about where to wire the funds
 * to authenticate as well as a hint as to which bank account to send
 * the funds from.
 */
struct ANASTASIS_WireFundsDetails
{

  /**
   * Answer code expected.
   */
  uint64_t answer_code;

  /**
   * How much should be sent.
   */
  struct TALER_Amount amount;

  /**
   * IBAN where to send the funds.
   */
  const char *target_iban;

  /**
   * Name of the business receiving the funds.
   */
  const char *target_business_name;

  /**
   * Wire transfer subject to use.
   */
  const char *wire_transfer_subject;

};


/**
 * Information returned for a POST /truth/$TID/challenge request.
 */
struct ANASTASIS_TruthChallengeDetails
{
  /**
   * HTTP status returned by the server.
   */
  unsigned int http_status;

  /**
   * Taler-specific error code, #TALER_EC_NONE on success.
   */
  enum TALER_ErrorCode ec;

  /**
   * Full response in JSON, if provided.
   */
  const json_t *response;

  /**
   * Details depending on @e http_status.
   */
  union
  {

    /**
     * Information for @e http_status of #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Meta-state about how the challenge was
       * initiated and what is to be done next.
       */
      enum ANASTASIS_ChallengeDetailType cs;

      /**
       * Details depending on @e cs.
       */
      union
      {

        /**
         * If @e cs is #ANASTASIS_CS_FILE_WRITTEN, this
         * is the filename with the challenge code.
         */
        const char *challenge_filename;

        /**
         * If @e cs is #ANASTASIS_CS_TAN_SENT, this
         * is human-readable information as to where
         * the TAN was sent.
         */
        const char *tan_address_hint;

        /**
         * If @e cs is #ANASTASIS_CS_WIRE_FUNDS, this
         * structure contains information about where
         * to wire the funds to authenticate as well
         * as a hint as to which bank account to send
         * the funds from.
         */
        struct ANASTASIS_WireFundsDetails wire_funds;

      } details;

    } success;

    /**
     * Information returned if @e http_status is #MHD_HTTP_PAYMENT_REQUIRED
     */
    struct
    {
      /**
       * A taler://pay/-URI with a request to pay the annual fee for
       * the service.  Returned if @e us is #ANASTASIS_US_PAYMENT_REQUIRED.
       */
      const char *payment_request;

      /**
       * The payment secret (aka order ID) extracted from the @e payment_request.
       */
      struct ANASTASIS_PaymentSecretP ps;

      /**
       * Data extracted from the payto:// URI.
       */
      const struct TALER_MERCHANT_PayUriData *pd;

    } payment_required;

  } details;

};


/**
 * Handle for a POST /truth/$TID/challenge operation.
 */
struct ANASTASIS_TruthChallengeOperation;


/**
 * Callback to process a POST /truth/$TID/challenge response.
 *
 * @param cls closure
 * @param tcd details about the key share
 */
#ifndef ANASTASIS_TRUTH_CHALLENGE_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_TruthChallengeCallback.
 */
#define ANASTASIS_TRUTH_CHALLENGE_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_TruthChallengeCallback) (
  ANASTASIS_TRUTH_CHALLENGE_RESULT_CLOSURE *cls,
  const struct ANASTASIS_TruthChallengeDetails *tcd);


/**
 * Makes a POST /truth/$TID/challenge request.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param truth_uuid identification of the Truth
 * @param truth_key Key used to Decrypt the Truth on the Server
 * @param payment_secret secret from the previously done payment NULL to trigger payment
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to the callback
 * @return handle for this operation, NULL upon errors
 */
struct ANASTASIS_TruthChallengeOperation *
ANASTASIS_truth_challenge (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
  const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
  const struct ANASTASIS_PaymentSecretP *payment_secret,
  ANASTASIS_TruthChallengeCallback cb,
  ANASTASIS_TRUTH_CHALLENGE_RESULT_CLOSURE *cb_cls);


/**
 * Cancel a POST /truth/$TID/challenge request.
 *
 * @param[in] tco operation to cancel
 */
void
ANASTASIS_truth_challenge_cancel (
  struct ANASTASIS_TruthChallengeOperation *tco);


/**
 * Information returned for a POST /truth/$TID/solve request.
 */
struct ANASTASIS_TruthSolveReply
{

  /**
   * HTTP status returned by the server.
   */
  unsigned int http_status;

  /**
   * Taler-specific error code, #TALER_EC_NONE on success.
   */
  enum TALER_ErrorCode ec;

  /**
   * Details depending on @e http_status.
   */
  union
  {

    /**
     * Information returned if @e http_status is #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * The encrypted key share.
       */
      struct ANASTASIS_CRYPTO_EncryptedKeyShareP eks;

    } success;

    /**
     * Information returned if @e http_status is #MHD_HTTP_PAYMENT_REQUIRED
     */
    struct
    {
      /**
       * A taler://pay/-URI with a request to pay the annual fee for
       * the service.  Returned if @e us is #ANASTASIS_US_PAYMENT_REQUIRED.
       */
      const char *payment_request;

      /**
       * The payment secret (aka order ID) extracted from the @e payment_request.
       */
      struct ANASTASIS_PaymentSecretP ps;

      /**
       * Data extracted from the payto:// URI.
       */
      const struct TALER_MERCHANT_PayUriData *pd;

    } payment_required;

    /**
     * Information returned if @e http_status is #MHD_HTTP_TOO_MANY_REQUESTS.
     */
    struct
    {

      /**
       * How many requests are allowed at most per @e request_frequency?
       */
      uint32_t request_limit;

      /**
       * Frequency at which requests are allowed / new challenges are
       * created.
       */
      struct GNUNET_TIME_Relative request_frequency;
    } too_many_requests;

  } details;

};


/**
 * Handle for a POST /truth/$TID/solve operation.
 */
struct ANASTASIS_TruthSolveOperation;


/**
 * Callback to process a POST /truth/$TID/solve response.
 *
 * @param cls closure
 * @param kdd details about the key share
 */
#ifndef ANASTASIS_TRUTH_SOLVE_RESULT_CLOSURE
/**
 * Type of the closure for #ANASTASIS_TruthSolveCallback.
 */
#define ANASTASIS_TRUTH_SOLVE_RESULT_CLOSURE void
#endif
typedef void
(*ANASTASIS_TruthSolveCallback) (
  ANASTASIS_TRUTH_SOLVE_RESULT_CLOSURE *cls,
  const struct ANASTASIS_TruthSolveReply *trs);


/**
 * Makes a POST /truth/$TID/solve request.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param truth_uuid identification of the Truth
 * @param truth_key Key used to Decrypt the Truth on the Server
 * @param payment_secret secret from the previously done payment NULL to trigger payment
 * @param timeout how long to wait for the payment, use
 *           #GNUNET_TIME_UNIT_ZERO to let the server pick
 * @param hashed_answer hashed answer to the challenge
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to the callback
 * @return handle for this operation, NULL upon errors
 */
struct ANASTASIS_TruthSolveOperation *
ANASTASIS_truth_solve (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
  const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
  const struct ANASTASIS_PaymentSecretP *payment_secret,
  struct GNUNET_TIME_Relative timeout,
  const struct GNUNET_HashCode *hashed_answer,
  ANASTASIS_TruthSolveCallback cb,
  ANASTASIS_TRUTH_SOLVE_RESULT_CLOSURE *cb_cls);


/**
 * Cancel a POST /truth/$TID/solve request.
 *
 * @param[in] tso handle of the operation to cancel
 */
void
ANASTASIS_truth_solve_cancel (
  struct ANASTASIS_TruthSolveOperation *tso);


#endif  /* _ANASTASIS_SERVICE_H */
