#ifndef SECP256K1_FROST_H #define SECP256K1_FROST_H #include "secp256k1.h" #include "secp256k1_extrakeys.h" #ifdef __cplusplus extern "C" { #endif #include #include /** 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. * * WARNING: the derivation above is the whole of what the nonce depends on. It * does NOT commit to the pubshares, to the untweaked threshold public key, or * to which tweaks the cache accumulated -- only to the x-only encoding of the * _tweaked_ threshold public key (this is BIP 445's det_nonce_hash, not a * deviation). Two tweak caches can therefore agree on that x-only key and * still disagree on the sign g*gacc that multiplies the secret share, because * Q and -Q have the same x-coordinate: a cache initialized from the threshold * public key and one initialized from its negation are the simplest example. * Two calls that differ only in that way emit the SAME pubnonce and two * partial signatures that differ only in the sign of the secret-share term, * which is two equations in the nonce and the secret share -- the secret * share falls out of the pair. * * The caller must therefore treat the tweak cache and the pubshares as fixed * key material belonging to the group, established once at key generation, * and never as per-session parameters accepted from a coordinator or any * other peer. Given that, repeating a call reproduces a byte-identical result * and is harmless, which is the point of a deterministic nonce. * * 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