-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce generics for common traits #68
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so great! Thanks for doing this
some minor comments
@@ -225,19 +201,19 @@ impl<P: Config> MerkleTree<P> { | |||
/// Create an empty merkle tree such that all leaves are zero-filled. | |||
/// Consider using a sparse merkle tree if you need the tree to be low memory | |||
pub fn blank( | |||
leaf_hash_param: &LeafParam<P>, | |||
two_to_one_hash_param: &TwoToOneParam<P>, | |||
leaf_hash_param: &LeafParams<P>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: probably better to change param
to params
for consistency?
P::TwoToOneHash, | ||
ConstraintF, | ||
OutputVar = Self::InnerDigest, | ||
pub trait ConfigGadget<ConstraintF: Field>: Config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that's great!
src/merkle_tree/constraints.rs
Outdated
P: Config, | ||
ConstraintF: Field, | ||
P::LeafHash: CRHSchemeGadget<ConstraintF, InputVar = P::LeafVar>, | ||
P::TwoToOneHash: TwoToOneCRHSchemeGadget<ConstraintF>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the bounds are probably not needed? The bound is already present in ConfigGadget
trait. Any config without such bound will not implement ConfigGadget
correctly, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately the bounds don't propagate =(
There's an RFC to fix that, but it's not implemented yet. Once it's implemented, I think the size of arkworks libraries will shrink by a large margin lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh no... hope that RFC will be stable soon
@@ -152,6 +134,7 @@ mod test { | |||
test_b.push(Fr::rand(&mut test_rng)); | |||
} | |||
|
|||
// TODO: figure out appropriate rate and capacity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weikengchen @ValarDragon what's an appropriate rate and capacity for this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is just a test example, let us do 2 and 1.
@@ -651,8 +651,6 @@ pub(crate) fn poseidon_parameters() -> PoseidonParameters<ark_ed_on_bls12_381::F | |||
vec![F::zero(), F::one(), F::one()], | |||
]; | |||
|
|||
// TODO: figure out appropriate rate and capacity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is just a test example, let us do 2 and 1.
Hi everyone, this PR should be reviewed in concert with arkworks-rs/r1cs-std#83. High-level overviewAt a high level, this PR reduces the boilerplate required for writing gadget code that is generic over the underlying components. Basically, instead of the following API: fn hash<H: Hash<ConstraintF>, HG: HashGadget<H, ConstraintF>, ConstraintF: Field>(input: &[UInt8<ConstraintF>) -> Vec<UInt8<ConstraintF>> {
HG::hash(input);
} we have the following API: fn hash<H: HashWithGadget<ConstraintF>, ConstraintF: Field>(input: &[UInt8<ConstraintF>) -> Vec<UInt8<ConstraintF>> {
Gadget::<H>::hash(input);
} Notice that we have fewer generic parameters, and furthermore it's conceptually cleaner: each "native" hash implementation has a single corresponding gadget implementation, instead of multiple possible ones implied by the current API: impl HashGadget<Pedersen, ConstraintF> for PedersenGadget {
...
}
impl HashGadget<Blake2s, ConstraintF> for PedersenGadget> {
...
} Design rationale:This PR proposes a new design for gadgets: /// Trait for the native version of the primitive
trait NativePrimitive {
// native methods and types, eg:
type Parameters;
fn evaluate(...) -> Vec<u8>;
}
/// Trait for the native version equipped with a gadget:
trait PrimitiveWithGadget<ConstraintF: Field> {
// gadget equivalents of the type
type ParametersVar;
fn evaluate_gadget(...) -> Vec<UInt8<ConstraintF>>;
}
/// Trait for use with `Gadget` type.
/// This is used mostly to allow using methods with appending gadget.
trait PrimitiveGadget<ConstraintF: Field> {
type Native: PrimitiveWithGadget<ConstraintF, ParametersVar = Self::ParametersVar>;
type ParametersVar;
// Note the default implementation here means that we can avoid
// duplicating code (and hence avoid errors)
// (Ideally we'd do the same for the associated types, but unfortunately
// associated type defaults are still unstable)
fn evaluate(...) -> Vec<UInt8<ConstraintF>> {
Self::Native::evaluate(...)
}
}
/// This blanket implementation means that implementors only need with implement
/// the `NativePrimitive` and `PrimitiveWithGadget` traits, and are
/// then immediately able to use `Gadget::<N>::evaluate`.
impl<N, ConstraintF: Field> PrimitiveGadget<ConstraintF> for Gadget<N>
where
N: PrimitiveWithGadget<ConstraintF>
{
type Native = N;
type ParametersVar = N::ParametersVar;
} This new API allows the simpler usage seen above. This design is somewhat more convoluted than necessary: it requires an extra trait, and indirection via the trait NativePrimitive {
type Parameters;
fn evaluate();
}
trait PrimitiveGadget: Native {
type ParametersVar;
fn evaluate();
} This is because in the following context the compiler doesn't know which method to invoke: fn thing<N: PrimitiveGadget>() {
N::evaluate(); // Should we pick NativePrimitive::evaluate, or PrimitiveGadget::evaluate?
} |
Description
closes: #63 by following the approach of arkworks-rs/r1cs-std#83
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
Pending
section inCHANGELOG.md
Files changed
in the Github PR explorer