Open
Description
Using many gadgets requires repeating type parameters: once for the native version, and once for the constraint version. However, this seems redundant as usually there's only a single gadget for a particular primitive. So, it makes sense to tie the gadget to the native impl. We can do this via an extension trait, as follows:
pub trait CRHGadget<ConstraintF: Field>: CRH {
type ParametersVar: AllocGadget<Self::Parameters>;
type InputVar: AllocGadget<Self::Input>;
type OutputVar: AllocGadget<Self::Output>;
fn evaluate(params: &Self::ParametersVar, input: &[UInt8]) -> R1CSResult<Self::OutputVar>;
}
impl CRHGadget for PedersenCRH { ... } // Note: this is implemented for *PedersenCRH*, not PedersenCRHGadget.
We can invoke this as
fn hash<H: CRHGadget<ConstraintF>, F: Field>(...) {
H::evaluate(¶ms, &input)?;
}
We've reduced the number of type parameters greatly. This works for Gadget
traits which don't contain variables themselves. What about Var
traits, which contain variables? We can still use them, as follows:
trait FieldExt {
type Var: FieldVar<...>;//figure out what to put in the type parameters.
}
impl FieldExt for FpN {
...
}
This would allow us to access the "unique" variable type for a given field element, without introducing multiple type parameters.
Feedback on this idea is very welcome!