/*
  This file is part of TALER
  Copyright (C) 2014-2026 Taler Systems SA

  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU Affero 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 Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License along with
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
/**
 * @file include/taler/exchange/post-reveal-melt.h
 * @brief C interface for POST /reveal-melt
 * @author Christian Grothoff
 */
#ifndef _TALER_EXCHANGE__POST_REVEAL_MELT_H
#define _TALER_EXCHANGE__POST_REVEAL_MELT_H

#include <taler/exchange/common.h>
#include <taler/exchange/get-keys.h>


/**
 * Information about a coin obtained via /reveal-melt.
 */
struct TALER_EXCHANGE_RevealedCoinInfo
{
  /**
   * Private key of the coin.
   */
  struct TALER_CoinSpendPrivateKeyP coin_priv;

  /**
   * Master secret of this coin.
   */
  struct TALER_PlanchetMasterSecretP ps;

  /**
   * Age commitment and its hash of the coin, might be NULL.
   */
  struct TALER_AgeCommitmentProof *age_commitment_proof;
  struct TALER_AgeCommitmentHashP h_age_commitment;

  /**
   * Blinding keys used to blind the fresh coin.
   */
  union GNUNET_CRYPTO_BlindingSecretP bks;

  /**
   * Signature affirming the validity of the coin.
   */
  struct TALER_DenominationSignature sig;

};


/**
 * The tuple of #TALER_CNC_KAPPA - 1 signatures, that are disclosed
 * during the /reveal-melt step.  From these signatures, signed with
 * the melted coin over refresh nonces, all input data is derived from
 * for the fresh coins.
 */
struct TALER_RevealPrivateRefreshNonceSignaturesP
{
  /**
   * Array of disclosed signatures.
   */
  struct TALER_PrivateRefreshNonceSignatureP tuple[TALER_CNC_KAPPA - 1];
};


/**
 * Information needed to melt (partially spent) coins to obtain fresh coins
 * that are unlinkable to the original coin(s).  Note that melting more than
 * one coin in a single request will make those coins linkable, so we only melt
 * one coin at a time.
 */
struct TALER_EXCHANGE_MeltInput
{
  /**
   * private key of the coin to melt
   */
  struct TALER_CoinSpendPrivateKeyP melt_priv;

  /**
   * age commitment and proof that went into the original coin,
   * might be NULL.
   */
  const struct TALER_AgeCommitmentProof *melt_age_commitment_proof;

  /**
   * Hash of age commitment and proof that went into the original coin,
   * might be NULL.
   */
  const struct TALER_AgeCommitmentHashP *melt_h_age_commitment;

  /**
   * amount specifying how much the coin will contribute to the melt
   * (including fee)
   */
  struct TALER_Amount melt_amount;

  /**
   * signatures affirming the validity of the public keys corresponding to the
   * @e melt_priv private key
   */
  struct TALER_DenominationSignature melt_sig;

  /**
   * denomination key information record corresponding to the @e melt_sig
   * validity of the keys
   */
  struct TALER_EXCHANGE_DenomPublicKey melt_pk;

  /**
   * length of the @e fresh_denom_pubs array
   */
  size_t num_fresh_denom_pubs;

  /**
   * array of @e num_fresh_coins denominations of fresh coins to create
   */
  const struct TALER_EXCHANGE_DenomPublicKey *fresh_denom_pubs;

};


/**
 * The necessary data of the /reveal-melt request, containing the input data
 * from the prior call to /melt and the information returned from it.
 */
struct TALER_EXCHANGE_RevealMeltInput
{
  /**
   * The public master seed for the melt/reveal, from which all other
   * secret material is derived from, using the old coin's private key.
   */
  const struct TALER_PublicRefreshMasterSeedP *rms;

  /**
   * The input data from the prior call to /melt
   */
  const struct TALER_EXCHANGE_MeltInput *melt_input;

  /**
   * The blinding seed that was used during the call to /melt.
   * Maybe NULL.
   */
  const struct TALER_BlindingMasterSeedP *blinding_seed;

  /**
   * Length of the @a blinding_values array with the exchange values
   * and blinding keys we are using.
   * MUST be the same as @e melt_input.num_fresh_denom_pubs.
   */
  unsigned int num_blinding_values;

  /**
   * Blinding values returned per coin.
   */
  const struct TALER_ExchangeBlindingValues *blinding_values;

  /**
   * Gamma value chosen by the exchange.
   */
  uint32_t noreveal_index;

};


/**
 * Handle for an operation to POST /reveal-melt.
 */
struct TALER_EXCHANGE_PostRevealMeltHandle;


/**
 * Set up POST /reveal-melt operation.
 * Note that you must explicitly start the operation after setup.
 *
 * This API is typically used by a wallet.  Note that to ensure that
 * no money is lost in case of hardware failures, the provided
 * argument @a reveal_melt_input should be committed to persistent storage
 * prior to calling this function.
 *
 * @param curl_ctx The curl context
 * @param exchange_url The base url of the exchange
 * @param reveal_melt_input The input data for the reveal
 * @return handle to operation, NULL on error
 */
struct TALER_EXCHANGE_PostRevealMeltHandle *
TALER_EXCHANGE_post_reveal_melt_create (
  struct GNUNET_CURL_Context *curl_ctx,
  const char *exchange_url,
  const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input);


/**
 * The response from a POST /reveal-melt request.
 */
struct TALER_EXCHANGE_PostRevealMeltResponse
{
  /**
   * HTTP response data.
   */
  struct TALER_EXCHANGE_HttpResponse hr;

  /**
   * Details about the response
   */
  union
  {
    /**
     * Details if the status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Array of @e num_coins values about the coins obtained via the refresh
       * operation.  The array give the coins in the same order (and should
       * have the same length) in which the original melt request specified the
       * respective denomination keys.
       */
      const struct TALER_EXCHANGE_RevealedCoinInfo *coins;

      /**
       * Number of coins returned.
       */
      unsigned int num_coins;
    } ok;

  } details;

};


#ifndef TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE
/**
 * Type of the closure used by
 * the #TALER_EXCHANGE_PostRevealMeltCallback.
 */
#define TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE void
#endif /* TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE */

/**
 * Type of the function that receives the result of a
 * POST /reveal-melt request.
 *
 * @param cls closure
 * @param result result returned by the HTTP server
 */
typedef void
(*TALER_EXCHANGE_PostRevealMeltCallback)(
  TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE *cls,
  const struct TALER_EXCHANGE_PostRevealMeltResponse *result);


/**
 * Start POST /reveal-melt operation.
 *
 * @param[in,out] prmh operation to start
 * @param cb function to call with the exchange's result
 * @param cb_cls closure for @a cb
 * @return status code, #TALER_EC_NONE on success
 */
enum TALER_ErrorCode
TALER_EXCHANGE_post_reveal_melt_start (
  struct TALER_EXCHANGE_PostRevealMeltHandle *prmh,
  TALER_EXCHANGE_PostRevealMeltCallback cb,
  TALER_EXCHANGE_POST_REVEAL_MELT_RESULT_CLOSURE *cb_cls);


/**
 * Cancel POST /reveal-melt operation.  This function must not be called by
 * clients after the TALER_EXCHANGE_PostRevealMeltCallback has been invoked
 * (as in those cases it'll be called internally by the implementation
 * already).
 *
 * @param[in] prmh operation to cancel
 */
void
TALER_EXCHANGE_post_reveal_melt_cancel (
  struct TALER_EXCHANGE_PostRevealMeltHandle *prmh);


#endif /* _TALER_EXCHANGE__POST_REVEAL_MELT_H */
