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

#ifndef SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H
#define SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H

#include <string.h>

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

#include "util.h"
#include "certeq.h"
#include "../../util.h"

/* The maximum length of an eq_input (and thus of the variable-length part of
 * a CertEq message): 4 + 33*t + 33*n + 33*n + 32*n with t, n <=
 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS. */
#define SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN (4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS)

/* certeq_message: pad33("BIP DKG/certeq message") || u32be(participant_id) ||
 * x. msg must hold 37 + x_len bytes. */
static void secp256k1_chilldkg_certeq_message(unsigned char *msg, const unsigned char *x, size_t x_len, uint32_t participant_id) {
    secp256k1_chilldkg_pad33(msg, "BIP DKG/certeq message");
    secp256k1_write_be32(msg + 33, participant_id);
    memcpy(msg + 37, x, x_len);
}

static int secp256k1_chilldkg_certeq_participant_step(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, uint32_t participant_id, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *aux_rand32) {
    unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN];
    int ret;

    VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN);
    secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, participant_id);
    ret = secp256k1_chilldkg_schnorrsig_sign(ctx, sig64, msg, 37 + eq_input_len, hostseckey32, aux_rand32, "BIP0340");
    secp256k1_memclear_explicit(msg, sizeof(msg));
    return ret;
}

static int secp256k1_chilldkg_certeq_verify(const secp256k1_context *ctx, const unsigned char *hostpubkeys33, size_t n, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *cert, uint32_t *fault_index) {
    unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN];
    size_t i;

    VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN);
    for (i = 0; i < n; i++) {
        secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, (uint32_t)i);
        /* Dropping the sign byte from hostpubkeys33[i] is okay because the
         * message commits to the full host public key. */
        if (!secp256k1_chilldkg_schnorrsig_verify(ctx, cert + 64 * i, msg, 37 + eq_input_len, hostpubkeys33 + 33 * i + 1, "BIP0340")) {
            *fault_index = (uint32_t)i;
            return 0;
        }
    }
    return 1;
}

#endif
