#ifndef SECP256K1_FROST_H
#define SECP256K1_FROST_H

#include "secp256k1.h"
#include "secp256k1_extrakeys.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>

/** This module implements BIP 445 "FROST Signing Protocol for BIP340
 *  Signatures" (https://github.com/siv2r/bip-frost-signing), a FROST3-based
 *  threshold Schnorr signature scheme.
 *
 *  This code is currently a work in progress. It's not secure nor stable.
 *  IT IS EXTREMELY DANGEROUS AND RECKLESS TO USE THIS MODULE IN PRODUCTION!
 *
 *  Since distributed key generation is out of scope for BIP 445, this module
 *  provides a trusted dealer for key generation
 *  (secp256k1_frost_trusted_dealer_keygen). Participants are identified by
 *  uint32 identifiers 0..n-1 (participant id i sits at polynomial x-coordinate
 *  i+1). The total number of participants n must not exceed
 *  SECP256K1_FROST_MAX_PARTICIPANTS.
 *
 *  A signing session involves u signers (threshold <= u <= n) and,
 *  optionally, a coordinator:
 *    1. Every signer runs secp256k1_frost_nonce_gen and sends the pubnonce to
 *       the coordinator.
 *    2. The coordinator aggregates the pubnonces with
 *       secp256k1_frost_nonce_agg and sends the aggnonce to the signers.
 *    3. Everyone runs secp256k1_frost_session_init on the same session
 *       parameters (aggnonce, signer ids, tweak cache, message).
 *    4. Every signer runs secp256k1_frost_sign and sends the partial signature
 *       to the coordinator.
 *    5. The coordinator verifies partial signatures with
 *       secp256k1_frost_partial_sig_verify and aggregates them with
 *       secp256k1_frost_partial_sig_agg.
 *
 *  It is recommended to read the documentation in this include file carefully.
 *  Further notes on API usage can be found in src/modules/frost/frost.md.
 */

/** The maximum number of participants n in a FROST setup. See BIP 445 for the
 *  security rationale behind this bound. */
#define SECP256K1_FROST_MAX_PARTICIPANTS 128

/** Opaque data structures
 *
 *  The exact representation of data inside the opaque data structures is
 *  implementation defined and not guaranteed to be portable between different
 *  platforms or versions. With the exception of `secp256k1_frost_secnonce`,
 *  the data structures can be safely copied/moved. If you need to convert to
 *  a format suitable for storage, transmission, or comparison, use the
 *  corresponding serialization and parsing functions.
 */

/** Opaque data structure that holds a signer's _secret_ nonce.
 *
 *  Guaranteed to be 68 bytes in size.
 *
 *  WARNING: This structure MUST NOT be copied or read or written to directly.
 *  A signer who is online throughout the whole process and can keep this
 *  structure in memory can use the provided API functions for a safe standard
 *  workflow.
 *
 *  Copying this data structure can result in nonce reuse which will leak the
 *  signer's secret share.
 */
typedef struct secp256k1_frost_secnonce {
    unsigned char data[68];
} secp256k1_frost_secnonce;

/** Opaque data structure that holds a signer's public nonce.
 *
 *  Guaranteed to be 132 bytes in size. Serialized and parsed with
 *  `frost_pubnonce_serialize` and `frost_pubnonce_parse`.
 */
typedef struct secp256k1_frost_pubnonce {
    unsigned char data[132];
} secp256k1_frost_pubnonce;

/** Opaque data structure that holds an aggregate public nonce.
 *
 *  Guaranteed to be 132 bytes in size. Serialized and parsed with
 *  `frost_aggnonce_serialize` and `frost_aggnonce_parse`.
 */
typedef struct secp256k1_frost_aggnonce {
    unsigned char data[132];
} secp256k1_frost_aggnonce;

/** Opaque data structure that caches the threshold public key and the state
 *  of public key tweaking.
 *
 *  Initialized with `frost_tweak_cache_init` from the (untweaked) threshold
 *  public key and required for `frost_session_init`. Tweaks are applied to
 *  the cache with `frost_pubkey_xonly_tweak_add` and
 *  `frost_pubkey_ec_tweak_add`.
 *
 *  Guaranteed to be 165 bytes in size. No serialization and parsing functions
 *  (yet).
 */
typedef struct secp256k1_frost_tweak_cache {
    unsigned char data[165];
} secp256k1_frost_tweak_cache;

/** Opaque data structure that holds a FROST signing session.
 *
 *  The session is signer-agnostic: the same session object can be used by a
 *  coordinator to verify the partial signatures of all signers. This
 *  structure is not required to be kept secret for the signing protocol to
 *  be secure. Guaranteed to be 137 bytes in size. No serialization and
 *  parsing functions (yet).
 */
typedef struct secp256k1_frost_session {
    unsigned char data[137];
} secp256k1_frost_session;

/** Opaque data structure that holds a partial FROST signature.
 *
 *  Guaranteed to be 36 bytes in size. Serialized and parsed with
 *  `frost_partial_sig_serialize` and `frost_partial_sig_parse`.
 */
typedef struct secp256k1_frost_partial_sig {
    unsigned char data[36];
} secp256k1_frost_partial_sig;

/** Parse a signer's public nonce.
 *
 *  Returns: 1 when the nonce could be parsed, 0 otherwise.
 *  Args:    ctx: pointer to a context object
 *  Out:   nonce: pointer to a nonce object
 *  In:     in66: pointer to the 66-byte nonce to be parsed
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubnonce_parse(
    const secp256k1_context *ctx,
    secp256k1_frost_pubnonce *nonce,
    const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Serialize a signer's public nonce
 *
 *  Returns: 1 always
 *  Args:    ctx: pointer to a context object
 *  Out:   out66: pointer to a 66-byte array to store the serialized nonce
 *  In:    nonce: pointer to the nonce
 */
SECP256K1_API int secp256k1_frost_pubnonce_serialize(
    const secp256k1_context *ctx,
    unsigned char *out66,
    const secp256k1_frost_pubnonce *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Parse an aggregate public nonce.
 *
 *  In contrast to `frost_pubnonce_parse`, this function accepts the point at
 *  infinity (encoded as 33 zero bytes) for either nonce component, as
 *  specified by BIP 445 NonceAgg.
 *
 *  Returns: 1 when the nonce could be parsed, 0 otherwise.
 *  Args:    ctx: pointer to a context object
 *  Out:   nonce: pointer to a nonce object
 *  In:     in66: pointer to the 66-byte nonce to be parsed
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_aggnonce_parse(
    const secp256k1_context *ctx,
    secp256k1_frost_aggnonce *nonce,
    const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Serialize an aggregate public nonce
 *
 *  A nonce component that is the point at infinity is encoded as 33 zero
 *  bytes, as specified by BIP 445.
 *
 *  Returns: 1 always
 *  Args:    ctx: pointer to a context object
 *  Out:   out66: pointer to a 66-byte array to store the serialized nonce
 *  In:    nonce: pointer to the nonce
 */
SECP256K1_API int secp256k1_frost_aggnonce_serialize(
    const secp256k1_context *ctx,
    unsigned char *out66,
    const secp256k1_frost_aggnonce *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Parse a FROST partial signature.
 *
 *  Returns: 1 when the signature could be parsed, 0 otherwise.
 *  Args:    ctx: pointer to a context object
 *  Out:     sig: pointer to a signature object
 *  In:     in32: pointer to the 32-byte signature to be parsed
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_parse(
    const secp256k1_context *ctx,
    secp256k1_frost_partial_sig *sig,
    const unsigned char *in32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Serialize a FROST partial signature
 *
 *  Returns: 1 always
 *  Args:    ctx: pointer to a context object
 *  Out:   out32: pointer to a 32-byte array to store the serialized signature
 *  In:      sig: pointer to the signature
 */
SECP256K1_API int secp256k1_frost_partial_sig_serialize(
    const secp256k1_context *ctx,
    unsigned char *out32,
    const secp256k1_frost_partial_sig *sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Generate threshold key material with a trusted dealer.
 *
 *  Implements the trusted dealer key generation of BIP 445: from the given
 *  threshold secret key, the dealer derives the secret share of every
 *  participant and the corresponding public shares. The dealer must transmit
 *  each secret share to its participant over a secure channel and erase all
 *  secret key material afterwards.
 *
 *  Returns: 0 if the arguments are invalid, 1 otherwise
 *  Args:            ctx: pointer to a context object
 *  Out:     secshares32: pointer to an n_participants*32-byte array to store
 *                        the secret shares; participant with id i receives
 *                        secshares32[i*32..(i+1)*32]
 *             thresh_pk: pointer to a pubkey object to store the threshold
 *                        public key (full point, parity is meaningful)
 *             pubshares: pointer to an array of n_participants pubkey
 *                        objects to store the public shares; entry i belongs
 *                        to the participant with id i
 *  In:   n_participants: total number of participants n. Must be between 1
 *                        and SECP256K1_FROST_MAX_PARTICIPANTS.
 *             threshold: threshold t. Must be between 1 and n_participants.
 *    threshold_seckey32: pointer to the 32-byte threshold secret key
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_trusted_dealer_keygen(
    const secp256k1_context *ctx,
    unsigned char *secshares32,
    secp256k1_pubkey *thresh_pk,
    secp256k1_pubkey *pubshares,
    size_t n_participants,
    uint32_t threshold,
    const unsigned char *threshold_seckey32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(7);

/** Validate threshold key material.
 *
 *  Implements ValidateThresholdInfo of BIP 445: checks that the public shares
 *  lie on a single polynomial and that they are consistent with the threshold
 *  public key. Note that this validates functional compatibility of the key
 *  material; it does NOT validate the security of the key generation that
 *  produced it.
 *
 *  Returns: 1 if the key material is valid and consistent, 0 otherwise
 *  Args:             ctx: pointer to a context object
 *  In:         thresh_pk: pointer to the threshold public key
 *              pubshares: array of n_participants pubkeys; entry i is the
 *                         public share of the participant with id i
 *         n_participants: total number of participants n
 *              threshold: threshold t
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_threshold_info_validate(
    const secp256k1_context *ctx,
    const secp256k1_pubkey *thresh_pk,
    const secp256k1_pubkey *pubshares,
    size_t n_participants,
    uint32_t threshold
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Initialize a tweak cache from the threshold public key.
 *
 *  The tweak cache is required for creating a signing session with
 *  `frost_session_init`, even if no tweaks are applied.
 *
 *  Returns: 0 if the arguments are invalid, 1 otherwise
 *  Args:     ctx: pointer to a context object
 *  Out:    cache: pointer to the tweak cache to initialize
 *  In: thresh_pk: pointer to the (untweaked) threshold public key
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_tweak_cache_init(
    const secp256k1_context *ctx,
    secp256k1_frost_tweak_cache *cache,
    const secp256k1_pubkey *thresh_pk
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Get the current (tweaked) threshold public key from a tweak cache.
 *
 *  This is the BIP340 x-only public key that final signatures of sessions
 *  created with this cache verify against.
 *
 *  Returns: 0 if the arguments are invalid, 1 otherwise
 *  Args:       ctx: pointer to a context object
 *  Out: tweaked_pk: pointer to an xonly_pubkey object to store the tweaked
 *                   threshold public key
 *  In:       cache: pointer to the tweak cache
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_tweaked_pubkey_get(
    const secp256k1_context *ctx,
    secp256k1_xonly_pubkey *tweaked_pk,
    const secp256k1_frost_tweak_cache *cache
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Apply an x-only tweak to the tweak cache.
 *
 *  Implements ApplyTweak of BIP 445 with is_xonly = true, i.e. BIP 341
 *  ("Taproot") tweaking: the current public key is negated if it has odd Y
 *  before the tweak is applied.
 *
 *  Returns: 0 if the arguments are invalid or the tweaked key would be the
 *           point at infinity, 1 otherwise
 *  Args:       ctx: pointer to a context object
 *  Out: tweaked_pk: pointer to an xonly_pubkey object to store the tweaked
 *                   threshold public key. If you do not need it, this arg can
 *                   be NULL.
 *  In:       cache: pointer to the tweak cache
 *          tweak32: pointer to the 32-byte tweak
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_xonly_tweak_add(
    const secp256k1_context *ctx,
    secp256k1_xonly_pubkey *tweaked_pk,
    secp256k1_frost_tweak_cache *cache,
    const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Apply a plain tweak to the tweak cache.
 *
 *  Implements ApplyTweak of BIP 445 with is_xonly = false, i.e. ordinary
 *  (BIP 32-style) tweaking: the current public key is not negated before the
 *  tweak is applied.
 *
 *  Returns: 0 if the arguments are invalid or the tweaked key would be the
 *           point at infinity, 1 otherwise
 *  Args:       ctx: pointer to a context object
 *  Out: tweaked_pk: pointer to an xonly_pubkey object to store the tweaked
 *                   threshold public key. If you do not need it, this arg can
 *                   be NULL.
 *  In:       cache: pointer to the tweak cache
 *          tweak32: pointer to the 32-byte tweak
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_ec_tweak_add(
    const secp256k1_context *ctx,
    secp256k1_xonly_pubkey *tweaked_pk,
    secp256k1_frost_tweak_cache *cache,
    const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Create a FROST nonce (pair) and its public counterpart.
 *
 *  Implements NonceGen of BIP 445. This function must only be called once per
 *  signing session; never reuse a secnonce for a second signature, as this
 *  leaks the secret share. To prevent reuse, this function wipes
 *  session_secrand32 before returning, and `frost_sign` wipes the secnonce.
 *
 *  Returns: 0 if the arguments are invalid, 1 otherwise
 *  Args:                 ctx: pointer to a context object
 *  Out:             secnonce: pointer to a secnonce object that will be
 *                             required for `frost_sign`
 *                   pubnonce: pointer to a pubnonce object to be sent to the
 *                             coordinator
 *  In/Out: session_secrand32: pointer to 32 bytes of fresh randomness. Must
 *                             be unique for every call. It is wiped before
 *                             this function returns.
 *  In:              secshare: pointer to the signer's 32-byte secret share,
 *                             or NULL. Providing the secret share adds
 *                             defense-in-depth against bad randomness (the
 *                             randomness is masked with the share, see
 *                             BIP 445 "Modifications to Nonce Generation").
 *                   pubshare: pointer to the signer's public share, or NULL
 *                thresh_pk32: pointer to the 32-byte x-only encoding of the
 *                             threshold public key the signature will verify
 *                             against (i.e. after applying tweaks, if any),
 *                             or NULL
 *                        msg: pointer to the message to be signed, or NULL if
 *                             the message is not known yet
 *                     msglen: length of msg. Must be 0 if msg is NULL.
 *                   extra_in: pointer to additional data to bind into the
 *                             nonce derivation, or NULL
 *               extra_in_len: length of extra_in. Must be 0 if extra_in is
 *                             NULL and at most 2^32 - 1 (the nonce hash
 *                             commits to it in a 4-byte length prefix).
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_nonce_gen(
    const secp256k1_context *ctx,
    secp256k1_frost_secnonce *secnonce,
    secp256k1_frost_pubnonce *pubnonce,
    unsigned char *session_secrand32,
    const unsigned char *secshare32,
    const secp256k1_pubkey *pubshare,
    const unsigned char *thresh_pk32,
    const unsigned char *msg,
    size_t msglen,
    const unsigned char *extra_in,
    size_t extra_in_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Aggregate the public nonces of the signers.
 *
 *  Implements NonceAgg of BIP 445. Note that the aggregate nonce may contain
 *  the point at infinity (if the corresponding column sums to it); this is
 *  not an error.
 *
 *  Returns: 0 if the arguments are invalid or one of the pubnonces is
 *           malformed, 1 otherwise
 *  Args:           ctx: pointer to a context object
 *  Out:       aggnonce: pointer to an aggnonce object
 *          error_index: if non-NULL, set to the index of the offending
 *                       pubnonce on failure
 *  In:       pubnonces: input array of pointers to pubnonces. The pubnonce at
 *                       index i must belong to the signer with ids[i] passed
 *                       to `frost_session_init`.
 *          n_pubnonces: length of the pubnonces array. Must be greater than
 *                       0.
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_nonce_agg(
    const secp256k1_context *ctx,
    secp256k1_frost_aggnonce *aggnonce,
    size_t *error_index,
    const secp256k1_frost_pubnonce *const *pubnonces,
    size_t n_pubnonces
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);

/** Initialize a FROST signing session.
 *
 *  Implements GetSessionValues of BIP 445: computes the nonce coefficient,
 *  the final nonce, and the BIP340 challenge. All signers and the coordinator
 *  must call this function with identical arguments (aside from ctx and
 *  session). The session is signer-agnostic; the coordinator can use it to
 *  verify the partial signatures of all signers.
 *
 *  Returns: 0 if the arguments are invalid (including inconsistent key
 *           material or duplicate signer ids), 1 otherwise
 *  Args:             ctx: pointer to a context object
 *  Out:          session: pointer to a session object
 *  In:          aggnonce: pointer to the aggregate nonce from
 *                         `frost_nonce_agg`
 *                    ids: array of the u signer identifiers. Every id must
 *                         be unique and smaller than n_participants.
 *              pubshares: array of u pubkeys with the public shares of the
 *                         signers (entry i belongs to ids[i]), or NULL if the
 *                         pubshares are unknown. If provided, they are
 *                         validated against the threshold public key.
 *              n_signers: number of signers u. Must be between threshold and
 *                         n_participants.
 *         n_participants: total number of participants n. Must be at most
 *                         SECP256K1_FROST_MAX_PARTICIPANTS.
 *              threshold: threshold t. Must be between 1 and n_participants.
 *            tweak_cache: pointer to the tweak cache holding the threshold
 *                         public key and all tweaks applied to it
 *                    msg: pointer to the message to sign, or NULL if
 *                         msglen is 0
 *                 msglen: length of msg
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_session_init(
    const secp256k1_context *ctx,
    secp256k1_frost_session *session,
    const secp256k1_frost_aggnonce *aggnonce,
    const uint32_t *ids,
    const secp256k1_pubkey *pubshares,
    size_t n_signers,
    size_t n_participants,
    uint32_t threshold,
    const secp256k1_frost_tweak_cache *tweak_cache,
    const unsigned char *msg,
    size_t msglen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(9) SECP256K1_ARG_NONNULL(10);

/** Produce a partial signature.
 *
 *  Implements Sign of BIP 445. Fails if my_id is not in the session's
 *  signer set. If pubshares is non-NULL, it must be the same array that was
 *  passed to `frost_session_init`, and the secret share is checked against
 *  the signer's public share (recommended; pass NULL only if the pubshares
 *  are unavailable). The secnonce is wiped by this function; calling it
 *  again with the same secnonce fails.
 *
 *  The same ids array that was passed to `frost_session_init` must be passed
 *  here.
 *
 *  Returns: 0 if the arguments are invalid or signing fails, 1 otherwise
 *  Args:             ctx: pointer to a context object
 *  Out:      partial_sig: pointer to a partial_sig object
 *  In:          secnonce: pointer to the signer's secnonce from
 *                         `frost_nonce_gen`
 *             secshare32: pointer to the signer's 32-byte secret share
 *                session: pointer to the session
 *                    ids: array of the u signer identifiers (identical to
 *                         session_init)
 *              pubshares: array of u pubkeys with the signers' public shares
 *                         (identical to session_init), or NULL
 *              n_signers: number of signers u
 *                  my_id: this signer's identifier
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_sign(
    const secp256k1_context *ctx,
    secp256k1_frost_partial_sig *partial_sig,
    secp256k1_frost_secnonce *secnonce,
    const unsigned char *secshare32,
    const secp256k1_frost_session *session,
    const uint32_t *ids,
    const secp256k1_pubkey *pubshares,
    size_t n_signers,
    uint32_t my_id
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

/** Produce a partial signature with a deterministically derived nonce.
 *
 *  Implements DeterministicSign of BIP 445. This function combines nonce
 *  generation and signing into one step for a signer that is online
 *  throughout the whole session. The nonce is derived deterministically from
 *  the secret share, the signer set, the other signers' aggregate nonce, the
 *  tweaked threshold public key, and the message; no secnonce object is
 *  involved.
 *
 *  A sole signer (u = 1) passes aggothernonce = NULL. Otherwise aggothernonce
 *  is the aggregate of all _other_ signers' pubnonces (obtainable via
 *  `frost_nonce_agg`). Unlike an aggnonce passed to `frost_session_init`, the
 *  aggothernonce must not contain the point at infinity (BIP 445 feeds it
 *  through NonceAgg as a pubnonce contribution, and a pubnonce's components
 *  are never the point at infinity); if it does, this function fails.
 *
 *  Returns: 0 if the arguments are invalid or signing fails, 1 otherwise
 *  Args:             ctx: pointer to a context object
 *  Out:      partial_sig: pointer to a partial_sig object
 *               pubnonce: pointer to a pubnonce object holding this signer's
 *                         public nonce, to be sent to the coordinator
 *  In:        secshare32: pointer to the signer's 32-byte secret share
 *                  my_id: this signer's identifier
 *          aggothernonce: pointer to the aggregate of the other signers'
 *                         public nonces, or NULL for a sole signer
 *                    ids: array of the u signer identifiers
 *              pubshares: array of u pubkeys with the signers' public
 *                         shares, or NULL
 *              n_signers: number of signers u
 *         n_participants: total number of participants n
 *              threshold: threshold t
 *            tweak_cache: pointer to the tweak cache
 *                    msg: pointer to the message to sign, or NULL if
 *                         msglen is 0
 *                 msglen: length of msg
 *             aux_rand32: pointer to 32 bytes of auxiliary randomness mixed
 *                         into the nonce derivation, or NULL
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_deterministic_sign(
    const secp256k1_context *ctx,
    secp256k1_frost_partial_sig *partial_sig,
    secp256k1_frost_pubnonce *pubnonce,
    const unsigned char *secshare32,
    uint32_t my_id,
    const secp256k1_frost_aggnonce *aggothernonce,
    const uint32_t *ids,
    const secp256k1_pubkey *pubshares,
    size_t n_signers,
    size_t n_participants,
    uint32_t threshold,
    const secp256k1_frost_tweak_cache *tweak_cache,
    const unsigned char *msg,
    size_t msglen,
    const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(12) SECP256K1_ARG_NONNULL(13);

/** Verify a partial signature.
 *
 *  Implements PartialSigVerify of BIP 445. The same ids array that was passed
 *  to `frost_session_init` must be passed here; signer_index is the index
 *  into that array identifying the signer whose partial signature is
 *  verified.
 *
 *  Returns: 1 if the partial signature is valid, 0 otherwise
 *  Args:             ctx: pointer to a context object
 *  In:       partial_sig: pointer to the partial signature
 *               pubnonce: pointer to the signer's public nonce
 *               pubshare: pointer to the signer's public share
 *                session: pointer to the session
 *                    ids: array of the u signer identifiers (identical to
 *                         session_init)
 *              n_signers: number of signers u
 *           signer_index: index of the signer in the ids array
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_verify(
    const secp256k1_context *ctx,
    const secp256k1_frost_partial_sig *partial_sig,
    const secp256k1_frost_pubnonce *pubnonce,
    const secp256k1_pubkey *pubshare,
    const secp256k1_frost_session *session,
    const uint32_t *ids,
    size_t n_signers,
    size_t signer_index
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

/** Aggregate partial signatures into a BIP340 signature.
 *
 *  Implements PartialSigAgg of BIP 445. The number of partial signatures must
 *  equal the number of signers u given to `frost_session_init`. The partial
 *  signature at index i must belong to the signer with ids[i].
 *
 *  Returns: 0 if the arguments are invalid or a partial signature cannot be
 *           parsed, 1 otherwise. Note that 1 does NOT mean that the resulting
 *           signature verifies; invalid partial signatures are only detected
 *           by `frost_partial_sig_verify`.
 *  Args:           ctx: pointer to a context object
 *  Out:          sig64: pointer to a 64-byte array to store the final
 *                       BIP340 signature
 *          error_index: if non-NULL, set to the index of the offending
 *                       partial signature on failure
 *  In:         session: pointer to the session
 *         partial_sigs: input array of pointers to partial signatures
 *               n_sigs: length of the partial_sigs array. Must equal
 *                       n_signers from `frost_session_init`.
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_partial_sig_agg(
    const secp256k1_context *ctx,
    unsigned char *sig64,
    size_t *error_index,
    const secp256k1_frost_session *session,
    const secp256k1_frost_partial_sig *const *partial_sigs,
    size_t n_sigs
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

#ifdef __cplusplus
}
#endif

#endif
