Manta-Network / manta-rs

Rust Crates for the Manta Network Ecosystem

Home Page:https://github.com/Manta-Network

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Investigate error with fuzzing test

SupremoUGH opened this issue · comments

Sometimes the CI fails and returns the error "Computing the field element from a big integer is not supposed to fail", coming from here:

fn fuzz<R>(&self, rng: &mut R) -> Self
where
R: RngCore + ?Sized,
{
P::from_repr(self.into_repr().fuzz(rng))
.expect("Computing the field element from a big integer is not supposed to fail.")
}

We should investigate why it sometimes fails.

Encountered this today, it fails because from_repr calls is_valid to check whether the given BigInteger represents a valid field element. The definition of is_valid is that the BigInteger is less than the modulus of the finite field.

So this fails because sometimes when fuzzing we change a bit that makes the resulting BigInteger have modulus larger than p.

Obviously from a mathematical point of view there's no such thing as an "invalid" BigInteger; any integer can be reduced modulo p. I guess that Arkworks made this choice to be able to assume later that all points are represented in a reduced form.

I guess one solution is to replace from_repr with something that handles reduction modulo p. For example,

P::new(self.into_repr().fuzz(rng)).const_reduce(P::MODULUS)

But maybe we should worry about what happens if fuzz changes the most significant bit to 1 and the loop in const_reduce becomes very long.

I think you're right about the reason and your solution seems ok. I'll look into it later.
I don't know the inner workings of const_reduce, but taking mod shouldn't be too expensive, right? And even if it is, we only use fuzz for testing (at least for now), so it shouldn't be too terrible. Also maybe it's better to do the mod P::MODULUS operation after fuzz and then use from_repr.
An alternative solution would be to do some error handling instead of expect, and in the case that fuzzing making BigInteger go above P::MODULUS to simply fuzz again until it doesn't happen, but I'd favour the first.