/***********************************************************************
 * Distributed under the MIT software license, see the accompanying    *
 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
 ***********************************************************************/

#ifndef SECP256K1_MODULE_FROST_KEYGEN_H
#define SECP256K1_MODULE_FROST_KEYGEN_H

#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_frost.h"

#include "../../group.h"
#include "../../hash.h"
#include "../../scalar.h"

typedef struct {
    /* The untweaked threshold public key (Q_0 in the specification). Required
     * for validating the signers' pubshares in session_init. Never the point
     * at infinity. */
    secp256k1_ge thresh_pk;
    /* The current (tweaked) threshold public key (Q in the specification).
     * Never the point at infinity. */
    secp256k1_ge pk;
    /* Accumulated tweak. Identical to tacc in the specification. */
    secp256k1_scalar tacc;
    /* gacc_parity corresponds to (1 - gacc)/2 in the specification. So if
     * gacc is -1, gacc_parity is 1. Otherwise, gacc_parity is 0. */
    int gacc_parity;
} secp256k1_frost_tweak_cache_internal;

static void secp256k1_frost_tweak_cache_save(secp256k1_frost_tweak_cache *cache, const secp256k1_frost_tweak_cache_internal *cache_i);

static int secp256k1_frost_tweak_cache_load(const secp256k1_context* ctx, secp256k1_frost_tweak_cache_internal *cache_i, const secp256k1_frost_tweak_cache *cache);

/* Computes the Lagrange interpolating value for signer my_id as defined in the
 * BIP 445 derive_interpolating_value algorithm: with x-coordinate of an
 * identifier id being id + 1, the value is
 *   lambda = product_{j != i} x_j / (x_j - x_i)  (mod n).
 * Returns 1 on success and 0 if my_id is not in ids or if ids contains
 * duplicates. Every uint32_t value is a valid identifier. */
static int secp256k1_frost_derive_interpolating_value(secp256k1_scalar *out, const uint32_t *ids, size_t n_ids, uint32_t my_id);

/* Evaluates the polynomial given by the pubshares at the identifier-space
 * point x (a scalar, i.e., identifier -1 is represented by -1 mod n), as
 * defined in the BIP 445 derive_pubshare_at algorithm. Returns 1 on success
 * and 0 if ids contains duplicates. The result may be the point at infinity;
 * the caller must handle that case. */
static int secp256k1_frost_derive_pubshare_at(secp256k1_gej *out, const uint32_t *ids, const secp256k1_ge *pubshares, size_t n_ids, const secp256k1_scalar *x);

/* Derives the threshold public key from the pubshares by evaluating the
 * polynomial at identifier -1 (i.e., x-coordinate 0), as defined in the
 * BIP 445 derive_thresh_pubkey algorithm. Returns 1 on success and 0 if ids
 * contains duplicates or the result is the point at infinity. */
static int secp256k1_frost_derive_thresh_pubkey(secp256k1_gej *out, const uint32_t *ids, const secp256k1_ge *pubshares, size_t n_ids);

#endif
