import { GrumpkinScalar, Point, Fr } from '@aztec/aztec.js';
import { Field, BoundedVec, Bool } from '@zkpersona/noir-helpers';

/**
 * Represents a SAG (Signature of Anonymous Group) ring signature.
 *
 * A ring signature allows a member of a group to sign a message on behalf of the group
 * without revealing which member actually created the signature. This provides
 * anonymity for the signer while still proving that the signature came from a member
 * of the specified group.
 *
 * @property c0 - The initial challenge value in the signature scheme. This is a scalar
 *                value on the Grumpkin curve that serves as the starting point for
 *                the verification process.
 * @property s - Array of response values for each ring member. Each value is a scalar
 *               on the Grumpkin curve that proves knowledge of the corresponding
 *               private key without revealing which one it is.
 * @property publicKeys - Array of public keys forming the ring. These are points on
 *                       the Grumpkin curve that represent the possible signers of the
 *                       message.
 */
interface RingSignature {
    c0: GrumpkinScalar;
    s: GrumpkinScalar[];
    publicKeys: Point[];
}

/**
 * Converts a SAG (Signature of Anonymous Group) ring signature to the format required
 * by the Noir circuit for verification.
 *
 * This function handles the conversion of:
 * - The initial challenge value (c0)
 * - The response values (s) for each ring member
 * - The public keys forming the ring
 * - The hashed message
 *
 * @param signature - The SAG ring signature to convert, containing:
 *   - c0: The initial challenge value
 *   - s: Array of response values for each ring member
 *   - publicKeys: Array of public keys forming the ring
 * @param messageFr - The hashed message as a field element
 * @param maxRingSize - The maximum number of public keys that can be in the ring
 *
 * @returns An object containing the converted inputs for the Noir circuit:
 *   - signature: The converted signature with c0 and s values
 *   - hashed_message: The converted hashed message
 *   - ring: The converted array of public keys
 */
declare const sagToNoirInputs: (signature: RingSignature, messageFr: Fr, maxRingSize: number) => {
    signature: {
        c0: Field;
        s: BoundedVec<Field, number>;
    };
    hashed_message: Field;
    ring: BoundedVec<{
        x: Field;
        y: Field;
        is_infinite: Bool;
    }, number>;
};

/**
 * Implementation of the SAG (Spontaneous Anonymous Group) ring signature scheme
 * using the Grumpkin curve and Pedersen hash function.
 *
 * This implementation provides a way to create and verify ring signatures,
 * which allow a member of a group to sign a message on behalf of the group
 * without revealing which specific member created the signature.
 *
 * @module sag
 */

/**
 * Creates a ring signature for a given message using the SAG scheme.
 *
 * The signing process involves:
 * 1. Generating a random scalar 'a' and computing aG
 * 2. Creating a chain of commitments using the public keys in the ring
 * 3. Computing the signature components (s values) for each ring member
 * 4. Using the signer's private key to close the ring
 *
 * @param hashedMessage - The message to be signed, already hashed to a field element
 * @param publicKeys - Array of public keys forming the ring
 * @param privateKey - Private key of the actual signer
 * @param signerIndex - Index of the signer's public key in the ring
 * @returns A ring signature containing the challenge c0, signature components s, and public keys
 */
declare const sign: (hashedMessage: Fr, publicKeys: Point[], privateKey: GrumpkinScalar, signerIndex: number) => Promise<RingSignature>;
/**
 * Verifies a ring signature against a given message.
 *
 * The verification process involves:
 * 1. Reconstructing the chain of commitments using the signature components
 * 2. Checking if the final challenge matches the initial challenge (c0)
 *
 * @param hashedMessage - The message to verify, already hashed to a field element
 * @param signature - The ring signature to verify
 * @returns True if the signature is valid, false otherwise
 */
declare const verify: (hashedMessage: Fr, signature: RingSignature) => Promise<boolean>;

export { sagToNoirInputs, sign, verify };
