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

#ifndef SECP256K1_MODULE_FROST_SESSION_H
#define SECP256K1_MODULE_FROST_SESSION_H

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

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

typedef struct {
    /* The x-coordinate of the final nonce R (x-only encoding). */
    unsigned char fin_nonce[32];
    /* The nonce coefficient b. */
    secp256k1_scalar noncecoef;
    /* The BIP340 challenge e. */
    secp256k1_scalar challenge;
    /* The scalar e*g*tacc added to the aggregate partial signature. */
    secp256k1_scalar s_part;
    /* The number of signers u. */
    uint32_t n_signers;
    /* 1 if the y-coordinate of the final nonce R is odd, 0 otherwise. */
    int fin_nonce_parity;
    /* g_times_gacc_parity corresponds to (1 - g*gacc)/2 in the specification,
     * where g is 1 if the (tweaked) threshold public key has even y and -1
     * otherwise. So if g*gacc is -1, g_times_gacc_parity is 1. */
    int g_times_gacc_parity;
} secp256k1_frost_session_internal;

/* Saves the two secret scalars k[0], k[1] into a secnonce. */
static void secp256k1_frost_secnonce_save(secp256k1_frost_secnonce *secnonce, const secp256k1_scalar *k);

/* Loads the two secret scalars from a secnonce. Fails (via ARG_CHECK) if the
 * secnonce is uninitialized or has been invalidated (e.g., by sign), which is
 * detected by checking the magic and that both scalars are nonzero. */
static int secp256k1_frost_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, const secp256k1_frost_secnonce *secnonce);

/* Saves two group elements into a pubnonce. Requires that none of the
 * provided group elements is infinity. */
static void secp256k1_frost_pubnonce_save(secp256k1_frost_pubnonce *nonce, const secp256k1_ge *ges);

/* Loads two group elements from a pubnonce. */
static int secp256k1_frost_pubnonce_load(const secp256k1_context* ctx, secp256k1_ge *ges, const secp256k1_frost_pubnonce *nonce);

/* Saves two group elements into an aggnonce. In contrast to a pubnonce, the
 * group elements are allowed to be the point at infinity. */
static void secp256k1_frost_aggnonce_save(secp256k1_frost_aggnonce *nonce, const secp256k1_ge *ges);

/* Loads two group elements from an aggnonce. Either element may be the point
 * at infinity. */
static int secp256k1_frost_aggnonce_load(const secp256k1_context* ctx, secp256k1_ge *ges, const secp256k1_frost_aggnonce *nonce);

static void secp256k1_frost_partial_sig_save(secp256k1_frost_partial_sig *sig, const secp256k1_scalar *s);

static int secp256k1_frost_partial_sig_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_frost_partial_sig *sig);

static void secp256k1_frost_session_save(secp256k1_frost_session *session, const secp256k1_frost_session_internal *session_i);

static int secp256k1_frost_session_load(const secp256k1_context* ctx, secp256k1_frost_session_internal *session_i, const secp256k1_frost_session *session);

#endif
