-
Notifications
You must be signed in to change notification settings - Fork 63
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
make nonnative gadget params configurable #129
base: master
Are you sure you want to change the base?
Conversation
@Pratyush @weikengchen can you please take a look? |
@slumber Could you also provide the corresponding fix for crypto-primitives? |
use super::NonNativeFieldConfig; | ||
|
||
/// Type that provides non native arithmetic configuration for a given pair of fields | ||
/// and optimization goal. | ||
pub trait Params: fmt::Debug + 'static { |
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 seems a bit too close to Config
; maybe we should rename it to something like ConfigBuilder
?
Also, does it make sense to make TargetField
and BaseField
associated types on this trait? This would reduce the number of type parameters everywhere else.
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 what do you think?
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 seems a bit too close to Config; maybe we should rename it to something like ConfigBuilder?
*Builder
is usually used for builder pattern, like
// build runtime
let runtime = Builder::new_multi_thread()
.worker_threads(4)
.thread_name("my-custom-name")
.thread_stack_size(3 * 1024 * 1024)
.build()
.unwrap();
Params
name is indeed very generic, it could be FindConfig
or ComputeParams
or whatever. I chose Params
because you can always do
use ark_r1cs_std::fields::nonnative::params::Params as FindNonNativeConfig;
But I'm OK with changing it to any other name.
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.
Also, does it make sense to make TargetField and BaseField associated types on this trait? This would reduce the number of type parameters everywhere else.
This would cause DefaultParams
to become generic, as you'll need DefaultParamsF1F2
for every field pair, because the trait can only be implemented once.
It's a question of whether Params
trait is defined for any pair of fields or for one particular. Given the original design, I believe it's the former, and this is reflected in the code.
I will once we're done with this PR. |
Co-authored-by: Pratyush Mishra <[email protected]>
@weikengchen @Pratyush can we have another iteration on this one? |
@slumber, sorry for the delay on this! Could you provide some example alternative instantiations of |
@Pratyush thank you for getting back to the PR. An example is computing poseidon hash. This is a sketch, but the idea should be clear; const MIN_SUPPORTED_LIMBS: usize = 3;
pub struct MinLimbsParams;
impl Params for MinLimbsParams {
fn get<TargetField: PrimeField, BaseField: PrimeField>(
_optimization_type: OptimizationType, // always minimize
) -> NonNativeFieldConfig {
let target_bits = TargetField::MODULUS_BIT_SIZE;
let base_bits = BaseField::MODULUS_BIT_SIZE;
let num_limbs = if target_bits >= base_bits {
MIN_SUPPORTED_LIMBS
} else {
(base_bits / target_bits).max(MIN_SUPPORTED_LIMBS)
};
let bits_per_limb = (base_bits / num_limbs).next_power_of_two();
NonNativeFieldConfig {
num_limbs: num_limbs as usize,
bits_per_limb: bits_per_limb as usize,
}
}
} Why put it as a generic parameter:
|
The primary concern I have is that users will need to specify an additional type parameter whenever they want to use This happens, for example, here: Line 51 in 4020fbc
In this case, we want to support scalar multiplication by any EmulatedFpVar as long as it is for the right field.
Would it be possible to have a different way to track the parameters? E.g. via a |
Yes, this bound wasn't present at the time of writing this PR. Being required to specify config in a trait definition doesn't appeal to me either.
partially:
If you think it's OK then I'll reimplement it with suggested change. |
@Pratyush on second thought, I don't think it's going to work because of object safety rules, at least I couldn't make it work in the playground |
@Pratyush what do you think about storing configuration directly in the struct: num_limbs: usize,
bits_per_limb: usize, And whenever you want to use non-default one you provide generic |
Depending on a goal, some developers would want to have a specific configuration perhaps with a smaller number
of limbs.
This change is almost backwards compatible and actually breaks some code in
ark-crypto-primitives
,but it tries to follow the pattern from Rust std like "Vec<T, A: Allocator = Global>"
Hence the new definition
Likewise for
AllocatedNonNativeFieldVar
,NonNativeFieldMulResultVar
,AllocatedNonNativeFieldMulResultVar
.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