import { asyncAggregateWithRandomness } from "@chainsafe/blst";
import { SignatureSetType } from "@lodestar/state-transition";
import { LinkedList } from "../../../util/array.js";
import { getAggregatedPubkey } from "../utils.js";
export { JobQueueItemType };
var JobQueueItemType;
(function (JobQueueItemType) {
    JobQueueItemType["default"] = "default";
    JobQueueItemType["sameMessage"] = "same_message";
})(JobQueueItemType || (JobQueueItemType = {}));
/**
 * Return count of signature sets from a JobQueueItem
 */
export function jobItemSigSets(job) {
    switch (job.type) {
        case JobQueueItemType.default:
            return job.sets.length;
        case JobQueueItemType.sameMessage:
            return 1;
    }
}
/**
 * Prepare BlsWorkReq from JobQueueItem
 * WARNING: May throw with untrusted user input
 */
export async function jobItemWorkReq(job, pubkeyCache, metrics) {
    switch (job.type) {
        case JobQueueItemType.default:
            return {
                opts: job.opts,
                sets: job.sets.map((set) => ({
                    // this can throw, handled in the consumer code
                    publicKey: getAggregatedPubkey(set, pubkeyCache, metrics).toBytes(),
                    signature: set.signature,
                    message: set.signingRoot,
                })),
            };
        case JobQueueItemType.sameMessage: {
            const timer = metrics?.blsThreadPool.aggregateWithRandomnessAsyncDuration.startTimer();
            const { pk, sig } = await asyncAggregateWithRandomness(job.sets.map((set) => ({ pk: set.publicKey, sig: set.signature })));
            timer?.();
            return {
                opts: job.opts,
                sets: [
                    {
                        publicKey: pk.toBytes(),
                        signature: sig.toBytes(),
                        message: job.message,
                    },
                ],
            };
        }
    }
}
/**
 * Convert a JobQueueItemSameMessage into multiple JobQueueItemDefault linked to the original promise
 */
export function jobItemSameMessageToMultiSet(job) {
    // Retry each individually
    // Create new jobs for each pubkey set, and Promise.all all the results
    const promises = [];
    const jobs = new LinkedList();
    for (const set of job.sets) {
        promises.push(new Promise((resolve, reject) => {
            jobs.push({
                type: JobQueueItemType.default,
                resolve,
                reject,
                addedTimeMs: job.addedTimeMs,
                opts: { batchable: false, priority: job.opts.priority },
                sets: [
                    {
                        type: SignatureSetType.single,
                        pubkey: set.publicKey,
                        signature: set.signature,
                        signingRoot: job.message,
                    },
                ],
            });
        }));
    }
    // Connect jobs to main job
    Promise.all(promises).then(job.resolve, job.reject);
    return jobs;
}
//# sourceMappingURL=jobItem.js.map