Impl arithmetic ops for Fields
Tracking an issue I faced during the ethglobal nyc hackathon. During the hackathon, I wanted to do things like implement counters using field elements. Doing so looked something like the following:
let counters_list = [BulletproofsField::from(0); 100];
for (i, f) in counters_list.into_iter().enumerate() {
if i == alices_index {
counters_list[i] = f + BulletproofsField::from(BigInt::ONE);
}
}
Currently, this is not possible because Add is not implemented for Field. I recommend Add be implemented, as well as all the other arithmetic methods. This would be a convenient change for devs, because the current state is that they would need to fork the repo to implement themselves.
This seems like an oversight on our part, thank you for pointing it out. We have arithmetic implementations for field elements F behind ProgramNodes so that you can do arithmetic within a #[zkp_program] function, and I guess we mostly considered the BulletproofsField type on its own to be used for providing static-ish arguments. But I can definitely see how it would be convenient to do some arithmetic on them outside of the ZKP program.
In the meantime, you could just do your arithmetic on a different integral type, and then cast to the BulletproofsField. Your example above would change to something like:
// Create the list out of u32s
let mut counters_list = [0u32; 100];
for (i, f) in counters_list.into_iter().enumerate() {
if i == alices_index {
counters_list[i] = f + 1;
}
}
// Then cast them all to BulletproofsField
let counters_list = counters_list.map(BulletproofsField::from);
For this particular example, there's also a nice stdlib function you could use:
let counters_list: [BulletproofsField; 100] = core::array::from_fn(|i| {
if i == alices_index {
1.into()
} else {
0.into()
}
});