0xPolygonZero / plonky2

Apache License 2.0
758 stars 281 forks source link

A problem in gadget `split_base` #1421

Closed xiyu1984 closed 9 months ago

xiyu1984 commented 9 months ago

If we use le_sum to convert a bits target(Vec<BoolTarget>) to a field target (just a Target related to a GoldilocksField), some values of the GoldilocksField will be invalid.

That is, we cannot set the target with the values in [2^63, 0xFFFFFFFF00000000] .

The order of a GoldilocksField is 0xFFFFFFFF00000001

xiyu1984 commented 9 months ago

I think the assert! makes big numbers in the GoldilocksField "lost".

But if we change the code:

assert!(
            num_bits <= log_floor(F::ORDER, 2),
            "{} bits may overflow the field",
            num_bits
);

to

assert!(
            num_bits <= log2_ceil(F::ORDER as usize),
            "{} bits may overflow the field",
            num_bits
);

And create a Target related to a GoldilocksField number through le_sum.

And set the target in the witness to any number larger than 2^63 and less than F::ORDER, the prove will work but the verify will fail. The error is as follows:

1702365565065

I think the restriction in the BaseSumGate is the reason.

wborgeaud commented 9 months ago

You are right that Goldilocks field elements with 64 bits are not reachable with this gadget, but we want to make sure it's impossible to overflow and this is only possible by rejecting 64 bit vectors altogether. In Plonky2 we only use this gadget with smaller vectors, so this isn't an issue for us. Do you have a use case where supporting 64 bit vectors is necessary?

xiyu1984 commented 9 months ago

You are right that Goldilocks field elements with 64 bits are not reachable with this gadget, but we want to make sure it's impossible to overflow and this is only possible by rejecting 64 bit vectors altogether. In Plonky2 we only use this gadget with smaller vectors, so this isn't an issue for us. Do you have a use case where supporting 64 bit vectors is necessary?

Yeah, in my case I need to prove the calculation of u128 numbers, and I found the BigUintTarget can do this. But in order to created the Poseidon hash of some data including the u128 numbers, I need to convert BigUintTarget to two Target related to two GoldilocksField values.

In order to do the converting, I transfer the BigUintTarget into bits first, and then use le_sum to generate two Targets related to two GoldilocksField. Sometimes the 64 bits BoolTarget vec reaches.

Anyway, luckily, I have solved this problem today, without any changed to the plonky2 repo.

The compromised solution is that, I generate a target with the first 63 bits, and add it to a constant target with the value ` 1 << 63 if the highest bit is 1.

If you have any better idea of this case, please let me know. Thanks~

wborgeaud commented 9 months ago

Ok great, will close this then.