#ifndef SECP256K1_CHILLDKG_H
#define SECP256K1_CHILLDKG_H

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

#ifdef __cplusplus
extern "C" {
#endif

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

/** This module implements ChillDKG, a distributed key generation (DKG)
 *  protocol for FROST, as specified by the bip-frost-dkg BIP draft
 *  (https://github.com/BlockstreamResearch/bip-frost-dkg, version 0.3.0-dev).
 *
 *  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!
 *
 *  Moreover, the bip-frost-dkg BIP is still a draft: tagged hashes, wire
 *  formats, and protocol details may change in future BIP versions. There is
 *  no guarantee that this implementation will remain compatible with the
 *  final specification.
 *
 *  The output of a ChillDKG session (a secret share, the threshold public
 *  key, and the public shares of all participants) is designed to be used
 *  directly with the FROST signing module (see include/secp256k1_frost.h).
 *
 *  A DKG session involves n participants (identified by uint32 identifiers
 *  0..n-1) and an untrusted coordinator. The number of participants n must
 *  not exceed SECP256K1_CHILLDKG_MAX_PARTICIPANTS. The message flow is:
 *    1. Every participant runs secp256k1_chilldkg_participant_step1 and sends
 *       the resulting pmsg1 to the coordinator.
 *    2. The coordinator runs secp256k1_chilldkg_coordinator_step1 on all
 *       pmsg1s and broadcasts the resulting cmsg1 to all participants.
 *    3. Every participant runs secp256k1_chilldkg_participant_step2 and sends
 *       the resulting signature (pmsg2) to the coordinator.
 *    4. The coordinator runs secp256k1_chilldkg_coordinator_finalize on all
 *       pmsg2s and broadcasts the resulting certificate (cmsg2) to all
 *       participants.
 *    5. Every participant runs secp256k1_chilldkg_participant_finalize to
 *       obtain the DKG output and the recovery data.
 *
 *  It is recommended to read the documentation in this include file carefully.
 *  Further notes on API usage can be found in src/modules/chilldkg/chilldkg.md.
 */

/** The maximum number of participants n in a ChillDKG session. The state
 *  objects of this module are fixed-size and do not use dynamic allocation,
 *  so a compile-time cap is required. This matches the FROST module's
 *  SECP256K1_FROST_MAX_PARTICIPANTS. */
#define SECP256K1_CHILLDKG_MAX_PARTICIPANTS 128

/** Fault report of the ChillDKG protocol functions, mapping the exception
 *  taxonomy of the reference implementation.
 *
 *  For SECP256K1_CHILLDKG_FAULTY_PARTICIPANT and
 *  SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, the fault_index
 *  output of the failing function is set to the identifier of the (suspected)
 *  faulty participant. For the other fault codes, fault_index is set to
 *  UINT32_MAX, except where documented otherwise. */
typedef enum {
    /** No fault; the step succeeded. */
    SECP256K1_CHILLDKG_OK = 0,
    /** The coordinator is faulty. */
    SECP256K1_CHILLDKG_FAULTY_COORDINATOR = 1,
    /** The participant with the given fault_index is faulty. */
    SECP256K1_CHILLDKG_FAULTY_PARTICIPANT = 2,
    /** The participant with the given fault_index or the coordinator is
     *  faulty. */
    SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR = 3,
    /** Some unknown participant or the coordinator is faulty; the
     *  investigation procedure of the protocol is necessary to determine a
     *  suspected participant. */
    SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR = 4,
    /** The caller provided invalid input (e.g., an invalid host secret key or
     *  invalid session parameters). */
    SECP256K1_CHILLDKG_INVALID_INPUT = 5
} secp256k1_chilldkg_fault;

/** 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. The data structures can be safely copied/moved.
 */

/** Opaque data structure that holds a participant's session state after
 *  secp256k1_chilldkg_participant_step1.
 *
 *  The state does not contain secret key material (the secret shares it
 *  relates to are encrypted in pmsg1), but it must not be reused: it must be
 *  passed only to a single secp256k1_chilldkg_participant_step2 call.
 *
 *  Guaranteed to be 4306 bytes in size.
 */
typedef struct secp256k1_chilldkg_participant_state1 {
    unsigned char data[4 + 12 + 33 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
} secp256k1_chilldkg_participant_state1;

/** Opaque data structure that holds a participant's session state after
 *  secp256k1_chilldkg_participant_step2.
 *
 *  This structure contains the participant's secret share; it MUST be kept
 *  secret and MUST NOT be copied. It must not be reused: it must be passed
 *  only to a single secp256k1_chilldkg_participant_finalize call.
 *
 *  Guaranteed to be 21073 bytes in size.
 */
typedef struct secp256k1_chilldkg_participant_state2 {
    unsigned char data[12 + 4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 32 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
} secp256k1_chilldkg_participant_state2;

/** Opaque data structure that holds the investigation data output by
 *  secp256k1_chilldkg_participant_step2 when it returns
 *  SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR, to be passed
 *  to secp256k1_chilldkg_participant_investigate together with the
 *  coordinator's investigation message.
 *
 *  This structure contains secret data (the untweaked secret share and the
 *  decryption pads); it MUST be kept secret.
 *
 *  Guaranteed to be 4205 bytes in size.
 */
typedef struct secp256k1_chilldkg_participant_inv_data {
    unsigned char data[12 + 32 + 33 + 32 + 32 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
} secp256k1_chilldkg_participant_inv_data;

/** Opaque data structure that holds the coordinator's session state after
 *  secp256k1_chilldkg_coordinator_step1, to be passed to
 *  secp256k1_chilldkg_coordinator_finalize (it must not be reused).
 *
 *  This structure contains no secret key material; it can be copied freely
 *  (e.g., to persist it between the two coordinator steps).
 *
 *  Guaranteed to be 21041 bytes in size.
 */
typedef struct secp256k1_chilldkg_coordinator_state {
    unsigned char data[12 + 4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
} secp256k1_chilldkg_coordinator_state;

/** Compute the participant's host public key from the host secret key.
 *
 *  The host public key is the long-term cryptographic identity of the
 *  participant. This function interprets hostseckey32 as a big-endian integer
 *  and computes the corresponding "plain" public key in compressed
 *  serialization (33 bytes, starting with 0x02 or 0x03), equivalent to
 *  IndividualPubkey as defined in BIP 327.
 *
 *  Returns: 1 on success, 0 if the host secret key is invalid (zero or not
 *           less than the group order). On failure, hostpubkey33 is set to
 *           zero.
 *  Args:          ctx: pointer to a context object
 *  Out:  hostpubkey33: pointer to a 33-byte array to store the host public key
 *  In:   hostseckey32: pointer to the 32-byte host secret key
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_hostpubkey_gen(
    const secp256k1_context *ctx,
    unsigned char *hostpubkey33,
    const unsigned char *hostseckey32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Return a hash of the session parameters for out-of-band comparison.
 *
 *  If all participants have obtained an identical parameters hash (as can be
 *  verified out of band), then they all agree on all host public keys and the
 *  threshold t.
 *
 *  Returns: 1 on success, 0 if the session parameters are invalid (not
 *           1 <= t <= n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS, an invalid
 *           host public key, or a duplicate host public key). On failure,
 *           hash32 is set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:           hash32: pointer to a 32-byte array to store the parameters
 *                         hash
 *  In:    hostpubkeys33: pointer to an array of n_participants host public
 *                        keys (33 bytes each, compressed serialization)
 *        n_participants: total number of participants n
 *             threshold: threshold t
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_params_hash(
    const secp256k1_context *ctx,
    unsigned char *hash32,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Length of a participant's first message (pmsg1): 33*t + 32*n + 97 bytes.
 *  Returns 0 if the parameters are out of range. */
SECP256K1_API size_t secp256k1_chilldkg_participant_msg1_len(
    size_t n_participants,
    uint32_t threshold
);

/** Length of the coordinator's first message (cmsg1): 162*n + 33*(t-1) bytes.
 *  Returns 0 if the parameters are out of range. */
SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg1_len(
    size_t n_participants,
    uint32_t threshold
);

/** Length of a participant's second message (pmsg2): 64 bytes. */
SECP256K1_API size_t secp256k1_chilldkg_participant_msg2_len(void);

/** Length of the coordinator's second message (cmsg2, the certificate):
 *  64*n bytes. Returns 0 if the parameters are out of range. */
SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg2_len(
    size_t n_participants
);

/** Length of the recovery data output by
 *  secp256k1_chilldkg_participant_finalize: 4 + 33*t + 162*n bytes.
 *  Returns 0 if the parameters are out of range. */
SECP256K1_API size_t secp256k1_chilldkg_recovery_data_len(
    size_t n_participants,
    uint32_t threshold
);

/** Perform a participant's first step of a ChillDKG session.
 *
 *  Returns: 1 on success, 0 on invalid input (invalid host secret key, host
 *           secret key not matching any host public key, invalid session
 *           parameters, or all-zero randomness). On failure, pmsg1 and the
 *           state are set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:          state1: pointer to a state1 object to be passed to
 *                        secp256k1_chilldkg_participant_step2 (must not be
 *                        reused)
 *                 pmsg1: pointer to a 33*t + 32*n + 97 byte array (see
 *                        secp256k1_chilldkg_participant_msg1_len) to store
 *                        the message to be sent to the coordinator
 *  In:     hostseckey32: pointer to the 32-byte host secret key
 *         hostpubkeys33: pointer to an array of n host public keys (33 bytes
 *                        each); all participants must agree on the order
 *        n_participants: total number of participants n
 *             threshold: threshold t
 *              random32: pointer to 32 bytes of FRESH randomness
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_participant_step1(
    const secp256k1_context *ctx,
    secp256k1_chilldkg_participant_state1 *state1,
    unsigned char *pmsg1,
    const unsigned char *hostseckey32,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold,
    const unsigned char *random32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8);

/** Perform a participant's second step of a ChillDKG session.
 *
 *  Verifies the coordinator's first message, computes the DKG output, and
 *  produces the CertEq signature over the session transcript.
 *
 *  **Warning:** After sending the produced signature to the coordinator, the
 *  caller **must not** erase the hostseckey, even if the coordinator reply
 *  needed for secp256k1_chilldkg_participant_finalize is not received (some
 *  other participant may deem the session successful and use the resulting
 *  threshold public key).
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success, otherwise a fault code:
 *           SECP256K1_CHILLDKG_INVALID_INPUT if the host secret key is
 *           invalid or does not match the one used in step 1;
 *           SECP256K1_CHILLDKG_FAULTY_COORDINATOR,
 *           SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, or
 *           SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR on
 *           protocol faults. On failure, sig64 and the state are set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:          state2: pointer to a state2 object to be passed to
 *                        secp256k1_chilldkg_participant_finalize (must not be
 *                        reused)
 *                 sig64: pointer to a 64-byte array to store the CertEq
 *                        signature (pmsg2) to be sent to the coordinator
 *           fault_index: pointer to a uint32 that receives the identifier of
 *                        the (suspected) faulty participant where applicable,
 *                        and UINT32_MAX otherwise
 *              inv_data: pointer to a participant_inv_data object that
 *                        receives the investigation data if (and only if) the
 *                        return value is
 *                        SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR,
 *                        or NULL if the caller does not intend to run
 *                        secp256k1_chilldkg_participant_investigate
 *  In:           state1: pointer to the state1 object output by
 *                        secp256k1_chilldkg_participant_step1
 *          hostseckey32: pointer to the 32-byte host secret key (must be the
 *                        same as in step 1)
 *                 cmsg1: pointer to the coordinator's first message
 *                        (162*n + 33*(t-1) bytes, see
 *                        secp256k1_chilldkg_coordinator_msg1_len)
 *            aux_rand32: pointer to 32 bytes of auxiliary randomness for the
 *                        CertEq signature (see BIP 340)
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(
    const secp256k1_context *ctx,
    secp256k1_chilldkg_participant_state2 *state2,
    unsigned char *sig64,
    uint32_t *fault_index,
    secp256k1_chilldkg_participant_inv_data *inv_data,
    const secp256k1_chilldkg_participant_state1 *state1,
    const unsigned char *hostseckey32,
    const unsigned char *cmsg1,
    const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8) SECP256K1_ARG_NONNULL(9);

/** Perform a participant's final step of a ChillDKG session.
 *
 *  Re-verifies all n CertEq signatures of the certificate and outputs the
 *  DKG output and the recovery data. If this function returns
 *  SECP256K1_CHILLDKG_OK, this participant deems the DKG session successful.
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success,
 *           SECP256K1_CHILLDKG_FAULTY_COORDINATOR if the certificate contains
 *           an invalid signature. As diagnostic information (deviating from
 *           the reference implementation, which does not report it),
 *           fault_index receives the index of the first invalid signature in
 *           the latter case. On failure, all outputs are set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:       secshare32: pointer to a 32-byte array to store the (tweaked)
 *                         secret share
 *            thresh_pk33: pointer to a 33-byte array to store the threshold
 *                         public key (compressed serialization)
 *           pubshares33: pointer to an array of n 33-byte elements to store
 *                        the public shares of all participants
 *              recovery: pointer to a 4 + 33*t + 162*n byte array (see
 *                        secp256k1_chilldkg_recovery_data_len) to store the
 *                        recovery data
 *           fault_index: pointer to a uint32 (see above)
 *  In:           state2: pointer to the state2 object output by
 *                        secp256k1_chilldkg_participant_step2
 *                 cmsg2: pointer to the coordinator's second message (the
 *                        certificate, 64*n bytes)
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_finalize(
    const secp256k1_context *ctx,
    unsigned char *secshare32,
    unsigned char *thresh_pk33,
    unsigned char *pubshares33,
    unsigned char *recovery,
    uint32_t *fault_index,
    const secp256k1_chilldkg_participant_state2 *state2,
    const unsigned char *cmsg2
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8);

/** Perform the coordinator's first step of a ChillDKG session.
 *
 *  Parses all n participant messages and aggregates them into the message to
 *  broadcast to all participants. The proofs of possession contained in the
 *  pmsg1s are NOT verified here; the participants verify them in step 2 (this
 *  mirrors the reference implementation).
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success,
 *           SECP256K1_CHILLDKG_INVALID_INPUT on invalid session parameters,
 *           or SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with fault_index set to
 *           the sender) if a participant message is malformed (invalid
 *           commitment encoding, or an encrypted share that overflows the
 *           group order). On failure, cmsg1 and the state are set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:           state: pointer to a coordinator_state object to be passed
 *                        to secp256k1_chilldkg_coordinator_finalize (must not
 *                        be reused)
 *                 cmsg1: pointer to a 162*n + 33*(t-1) byte array (see
 *                        secp256k1_chilldkg_coordinator_msg1_len) to store
 *                        the message to be broadcast to all participants
 *           fault_index: pointer to a uint32 that receives the identifier of
 *                        the faulty participant where applicable, and
 *                        UINT32_MAX otherwise
 *  In:           pmsgs1: array of n pointers to the participants' first
 *                        messages (33*t + 32*n + 97 bytes each)
 *         hostpubkeys33: pointer to an array of n host public keys (33 bytes
 *                        each); must be identical (in content and order) to
 *                        the arrays used by the participants
 *        n_participants: total number of participants n
 *             threshold: threshold t
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_step1(
    const secp256k1_context *ctx,
    secp256k1_chilldkg_coordinator_state *state,
    unsigned char *cmsg1,
    uint32_t *fault_index,
    const unsigned char *const *pmsgs1,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

/** Perform the coordinator's final step of a ChillDKG session.
 *
 *  Collects the n CertEq signatures into the certificate and verifies all of
 *  them. If this function returns SECP256K1_CHILLDKG_OK, the coordinator
 *  deems the DKG session successful.
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success, or
 *           SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with fault_index set to
 *           the signer) if a CertEq signature is invalid. On failure, all
 *           outputs are set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:           cmsg2: pointer to a 64*n byte array to store the
 *                        certificate, to be broadcast to all participants
 *            thresh_pk33: pointer to a 33-byte array to store the threshold
 *                         public key (compressed serialization)
 *           pubshares33: pointer to an array of n 33-byte elements to store
 *                        the public shares of all participants
 *              recovery: pointer to a 4 + 33*t + 162*n byte array (see
 *                        secp256k1_chilldkg_recovery_data_len) to store the
 *                        recovery data
 *           fault_index: pointer to a uint32 (see above)
 *  In:            state: pointer to the coordinator_state object output by
 *                        secp256k1_chilldkg_coordinator_step1
 *                pmsgs2: array of n pointers to the participants' second
 *                        messages (64 bytes each)
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_finalize(
    const secp256k1_context *ctx,
    unsigned char *cmsg2,
    unsigned char *thresh_pk33,
    unsigned char *pubshares33,
    unsigned char *recovery,
    uint32_t *fault_index,
    const secp256k1_chilldkg_coordinator_state *state,
    const unsigned char *const *pmsgs2
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8);

/** Length of a coordinator investigation message (cinv): 65*n bytes (n
 *  encrypted partial secret shares of 32 bytes each, followed by n partial
 *  public shares of 33 bytes each). Returns 0 if n is out of range. */
SECP256K1_API size_t secp256k1_chilldkg_investigation_msg_len(
    size_t n_participants
);

/** Recover the DKG output of a participant from recovery data.
 *
 *  This function serves two purposes: recovering from a failure of
 *  secp256k1_chilldkg_participant_finalize after obtaining the recovery data
 *  from another participant or the coordinator, and reproducing the DKG
 *  outputs on a new device (e.g., after data loss).
 *
 *  The recovery data (see secp256k1_chilldkg_recovery_data_len) is
 *  self-delimiting: the number of participants n and the threshold t are
 *  derived from its length and contents.
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success,
 *           SECP256K1_CHILLDKG_INVALID_INPUT if the recovery data is invalid
 *           (this includes an invalid certificate) or if the host secret key
 *           is invalid or does not match any host public key in the recovery
 *           data (RecoveryDataError and HostSeckeyError in the reference
 *           implementation), or
 *           SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR (with
 *           fault_index set) if a pubnonce in the recovery data is invalid.
 *           On failure, secshare32 and thresh_pk33 are set to zero and
 *           *n_participants_out and *threshold_out are set to 0; pubshares33
 *           and hostpubkeys33_out are set to zero whenever n could be
 *           determined.
 *  Args:                  ctx: pointer to a context object
 *  Out:            secshare32: pointer to a 32-byte array to store the
 *                              (tweaked) secret share
 *                 thresh_pk33: pointer to a 33-byte array to store the
 *                              threshold public key (compressed serialization)
 *                pubshares33: pointer to an array capable of holding
 *                              33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
 *                              to store the public shares (33 bytes each; the
 *                              first n entries are filled)
 *             hostpubkeys33_out: pointer to an array capable of holding
 *                              33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
 *                              to store the host public keys of the recovered
 *                              session (the first n entries are filled)
 *          n_participants_out: pointer to a size_t to store the number of
 *                              participants n of the recovered session
 *               threshold_out: pointer to a uint32 to store the threshold t
 *                              of the recovered session
 *                fault_index: pointer to a uint32 that receives the identifier
 *                              of the suspected participant where applicable,
 *                              and UINT32_MAX otherwise
 *  In:           hostseckey32: pointer to the 32-byte host secret key
 *                    recovery: pointer to the recovery data
 *               recovery_len: length of the recovery data
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_recover(
    const secp256k1_context *ctx,
    unsigned char *secshare32,
    unsigned char *thresh_pk33,
    unsigned char *pubshares33,
    unsigned char *hostpubkeys33_out,
    size_t *n_participants_out,
    uint32_t *threshold_out,
    uint32_t *fault_index,
    const unsigned char *hostseckey32,
    const unsigned char *recovery,
    size_t recovery_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8) SECP256K1_ARG_NONNULL(9) SECP256K1_ARG_NONNULL(10);

/** Recover the DKG output of the coordinator from recovery data.
 *
 *  Like secp256k1_chilldkg_participant_recover, but for the coordinator, who
 *  has no secret share.
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success,
 *           SECP256K1_CHILLDKG_INVALID_INPUT if the recovery data is invalid.
 *           On failure, thresh_pk33 is set to zero and *n_participants_out
 *           and *threshold_out are set to 0; pubshares33 and
 *           hostpubkeys33_out are set to zero whenever n could be determined.
 *  Args:                  ctx: pointer to a context object
 *  Out:            thresh_pk33: pointer to a 33-byte array to store the
 *                              threshold public key (compressed serialization)
 *                pubshares33: pointer to an array capable of holding
 *                              33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
 *                              to store the public shares (the first n
 *                              entries are filled)
 *             hostpubkeys33_out: pointer to an array capable of holding
 *                              33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS bytes
 *                              to store the host public keys of the recovered
 *                              session (the first n entries are filled)
 *          n_participants_out: pointer to a size_t to store n
 *               threshold_out: pointer to a uint32 to store t
 *  In:               recovery: pointer to the recovery data
 *               recovery_len: length of the recovery data
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_recover(
    const secp256k1_context *ctx,
    unsigned char *thresh_pk33,
    unsigned char *pubshares33,
    unsigned char *hostpubkeys33_out,
    size_t *n_participants_out,
    uint32_t *threshold_out,
    const unsigned char *recovery,
    size_t recovery_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7);

/** Sign recovery data to create a recovery acknowledgment.
 *
 *  The acknowledgment signature (64 bytes) is a BIP 340 signature over
 *  pad33("BIP DKG/recovery acknowledgment") || u32be(participant_id) ||
 *  recovery_data under the participant's host key. Acks can be collected in
 *  an optional acknowledgment round to confirm that all participants have
 *  received the recovery data.
 *
 *  Returns: 1 on success, 0 on invalid input (invalid host secret key, host
 *           secret key not matching any host public key, invalid session
 *           parameters, or recovery data that is invalid or does not match
 *           the session parameters). On failure, sig64 is set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:           sig64: pointer to a 64-byte array to store the
 *                        acknowledgment signature
 *  In:     hostseckey32: pointer to the 32-byte host secret key
 *         hostpubkeys33: pointer to an array of n host public keys (33 bytes
 *                        each)
 *        n_participants: total number of participants n
 *             threshold: threshold t
 *              recovery: pointer to the recovery data
 *           recovery_len: length of the recovery data
 *            aux_rand32: pointer to 32 bytes of auxiliary randomness (see
 *                        BIP 340)
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_recovery_ack_sign(
    const secp256k1_context *ctx,
    unsigned char *sig64,
    const unsigned char *hostseckey32,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold,
    const unsigned char *recovery,
    size_t recovery_len,
    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(9);

/** Verify recovery acknowledgment signatures from all participants.
 *
 *  Note that a failure of this function does NOT mean the DKG failed
 *  (reaching this point implies the DKG itself was successful). It only means
 *  it cannot be confirmed that all participants have a copy of the recovery
 *  data.
 *
 *  Returns: SECP256K1_CHILLDKG_OK if all n acknowledgment signatures are
 *           valid, SECP256K1_CHILLDKG_INVALID_INPUT on invalid session
 *           parameters or recovery data, or SECP256K1_CHILLDKG_FAULTY_PARTICIPANT
 *           (with fault_index set to the signer) if an acknowledgment
 *           signature is invalid (InvalidRecoveryAckError in the reference
 *           implementation).
 *  Args:             ctx: pointer to a context object
 *  Out:     fault_index: pointer to a uint32 that receives the identifier of
 *                        the participant whose signature is invalid, where
 *                        applicable, and UINT32_MAX otherwise
 *  In:     hostpubkeys33: pointer to an array of n host public keys (33 bytes
 *                        each)
 *        n_participants: total number of participants n
 *             threshold: threshold t
 *              recovery: pointer to the recovery data
 *           recovery_len: length of the recovery data
 *              ack_sigs64: array of n pointers to the acknowledgment
 *                        signatures (64 bytes each), in the same order as
 *                        hostpubkeys33
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_recovery_acks_verify(
    const secp256k1_context *ctx,
    uint32_t *fault_index,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold,
    const unsigned char *recovery,
    size_t recovery_len,
    const unsigned char *const *ack_sigs64
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(8);

/** Generate the investigation message for a single participant.
 *
 *  The investigation message (65*n bytes, see
 *  secp256k1_chilldkg_investigation_msg_len) allows the given participant to
 *  investigate who is to blame for a failed ChillDKG session (see
 *  secp256k1_chilldkg_participant_investigate). The message contains no
 *  confidential information and can be safely broadcast. (Unlike the
 *  reference implementation, which computes the investigation messages for
 *  all participants at once, this function computes one message per call.)
 *
 *  Returns: SECP256K1_CHILLDKG_OK on success,
 *           SECP256K1_CHILLDKG_INVALID_INPUT on invalid session parameters or
 *           participant_id >= n, or SECP256K1_CHILLDKG_FAULTY_PARTICIPANT
 *           (with fault_index set to the sender) if a participant message is
 *           malformed. On failure, cinv is set to zero.
 *  Args:             ctx: pointer to a context object
 *  Out:           cinv: pointer to a 65*n byte array to store the
 *                        investigation message for the given participant
 *           fault_index: pointer to a uint32 (see above)
 *  In:          pmsgs1: array of n pointers to the participants' first
 *                        messages (33*t + 32*n + 97 bytes each)
 *         hostpubkeys33: pointer to an array of n host public keys (33 bytes
 *                        each)
 *        n_participants: total number of participants n
 *             threshold: threshold t
 *         participant_id: the participant the investigation message is for
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_coordinator_investigate(
    const secp256k1_context *ctx,
    unsigned char *cinv,
    uint32_t *fault_index,
    const unsigned char *const *pmsgs1,
    const unsigned char *hostpubkeys33,
    size_t n_participants,
    uint32_t threshold,
    uint32_t participant_id
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Investigate who is to blame for a failed ChillDKG session.
 *
 *  This function can be called when secp256k1_chilldkg_participant_step2
 *  returned SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR. It
 *  narrows down the suspected faulty parties by analyzing the investigation
 *  message provided by the coordinator.
 *
 *  Returns: SECP256K1_CHILLDKG_FAULTY_COORDINATOR if the coordinator is
 *           faulty, SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR
 *           (with fault_index set to the suspected participant) if another
 *           participant or the coordinator is faulty, or
 *           SECP256K1_CHILLDKG_INVALID_INPUT if all inputs are consistent
 *           (i.e., the function was called even though no fault occurred).
 *  Args:             ctx: pointer to a context object
 *  Out:     fault_index: pointer to a uint32 (see above)
 *  In:        inv_data: pointer to the participant_inv_data object output by
 *                        secp256k1_chilldkg_participant_step2
 *                  cinv: pointer to the coordinator's investigation message
 *                        for this participant (65*n bytes, see
 *                        secp256k1_chilldkg_investigation_msg_len)
 */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_investigate(
    const secp256k1_context *ctx,
    uint32_t *fault_index,
    const secp256k1_chilldkg_participant_inv_data *inv_data,
    const unsigned char *cinv
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

#ifdef __cplusplus
}
#endif

#endif
