Skip to content

FROST pre_commitment hooks for custom group commitment behaviour #906

@scaraven

Description

@scaraven

Hi,

I am part of a small team working on creating a FROST integration to provide multi-sig capabilities on Mina Protocol.

We ran into the issue in that Mina protocol Schnorr signatures require that the signature commitment (the group commitment within FROST) must have an even Y coordinate which FROST does not care about and therefore gives us a 50% chance that a valid FROST signature is valid on the Mina protocol.

As discussed already on the ZCash Forum, the solution to this is negating nonces and commitments when the group commitment within FROST has an odd Y value. However, the fix requires me to copy a large majority of code in order to modify a few lines.

I was wondering whether it is feasible to add pre_commitment_sign and pre_commitment_aggregate functions within frost-core:

frost::round2::sign

let binding_factor_list: BindingFactorList<C> =
            compute_binding_factor_list(&signing_package, key_package.verifying_key(), &[])?;
let binding_factor: frost::BindingFactor<C> = binding_factor_list
    .get(key_package.identifier())
    .ok_or(Error::UnknownIdentifier)?
    .clone();

// Perform pre_group_commitment to check if the group commitment is even
+ let (signing_package, signer_nonces) = pre_commitment_sign(&signing_package, &signer_nonces, &binding_factor_list)?;

 // Compute the group commitment from signing commitments produced in round one.
let group_commitment = compute_group_commitment(&signing_package, &binding_factor_list)?;

frost::aggregate

// Encodes the signing commitment list produced in round one as part of generating [`BindingFactor`], the
// binding factor.
let binding_factor_list: BindingFactorList<C> =
    compute_binding_factor_list(&signing_package, pubkeys.verifying_key(), &[])?;
+ let signing_package = pre_commitment_aggregate(&signing_package, &binding_factor_list)?;

// Compute the group commitment from signing commitments produced in round one.
let group_commitment = compute_group_commitment(&signing_package, &binding_factor_list)?;

Where the function signatures would look like:

pub fn pre_commitment_sign<'a, C: Ciphersuite>(
    signing_package: &'a SigningPackage,
    signing_nonces: &'a SigningNonces,
    binding_factor_list: &'a BindingFactorList<C>,
) -> Result<(Cow<'a, SigningPackage>, Cow<'a, SigningNonces>), Error> {}
pub fn pre_commitment_aggregate<'a, C: Ciphersuite>(
    signing_package: &'a SigningPackage,
    binding_factor_list: &'a BindingFactorList<C>,
) -> Result<Cow<'a, SigningPackage>, Error> {}

This change should be backwards-incompatible and by default will act as no-ops.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions