Skip to content

Make FieldElement generic to simplify alternate backend creation. #5055

@Philogy

Description

@Philogy

Problem

Personally, I'm very bullish on the vision for Noir to become "the LLVM of ZK" which is why we recently attempted to (and somewhat succeeded) at developing an MVP alternate backend for Noir that targets a different proving system (AIR+FRI STARK) that also uses a different prime field (BabyBear).

This was made unnecessarily difficult by the fact that the commonly referred to FieldElement type is dynamically defined at compile time via feature flags propagated throughout the codebase (relevant snippet):

cfg_if::cfg_if! {
    if #[cfg(feature = "bn254")] {
        mod generic_ark;
        pub type FieldElement = generic_ark::FieldElement<ark_bn254::Fr>;
        pub const CHOSEN_FIELD : FieldOptions = FieldOptions::BN254;

    } else if #[cfg(feature = "bls12_381")] {
        mod generic_ark;
        pub type FieldElement = generic_ark::FieldElement<ark_bls12_381::Fr>;
        pub const CHOSEN_FIELD : FieldOptions = FieldOptions::BLS12_381;
    } else {
        compile_error!("please specify a field to compile with");
    }
}

This was further complicated by the fact that bn254 is the default feature, meaning that despite adding a 3rd curve here and defining the feature for it the flags had to be changed in all relevant sub-crates of our fork as well as leading to hard to track down assert_unique_feature errors arising from crates seemingly still referencing the bn254 feature (The difficulty of tracking down the issue was mainly because Rust wouldn't tell us which crate is implicitly using the conflicting bn254 feature flag but instead just point to the defined compile-time check).

In the hackathon we fixed this by just deleting crates we didn't immediately need and updating the features wherever we could.

Happy Case

Ideally FieldElement would be defined and propagated through the crates as a generic type, only being fixed at top-level interaction points such as nargo_cli so that forks can select/switch the field.

Even better would be if custom prime fields were definable or pre-existing fields selectable via options in your Nargo.toml file.

Project Impact

Blocker

Impact Context

When it comes to building alternative backends this is a fundamental blocker as creating and integrating a new one would require making the aforementioned non-trivial changes to the codebase, requiring devs to install, compile and run forks of noir which is sub-optimal.

Workaround

None

Workaround Description

No response

Additional Context

No response

Would you like to submit a PR for this Issue?

None

Support Needs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendProving backendsenhancementNew feature or request

    Type

    No type

    Projects

    Status

    📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions