diff --git a/logproof/src/linear_relation.rs b/logproof/src/linear_relation.rs index 0764af5bb..07063bdf3 100644 --- a/logproof/src/linear_relation.rs +++ b/logproof/src/linear_relation.rs @@ -833,13 +833,64 @@ impl LogProof { (r_2, r_1) } + /** + * Takes an individual values in a field `Zq`, treats the value as signed [q's + * complement](https://en.wikipedia.org/wiki/Method_of_complements) and + * converts the value to binary 2's complement. This is then appended to an + * provided BitVec. + * + * `value` is the element in Zq and `b` is the number of bits needed + * to represent the signed value. + * + * This modifies bitvec in place. + * + */ + fn to_2s_complement_single( + value: &Fp, N>, + log_b: u64, + bitvec: &mut BitVec, + ) where + Q: MontConfig, + { + // Get the value out of Montgomery form. + let value = MontBackend::into_bigint(*value); + + let mod_div_2 = Fp::, N>::field_modulus_div_2(); + let modulus = Fp::, N>::field_modulus(); + let is_negative = value > mod_div_2; + + // Compute the q's complement of value + let mut as_neg: BigInt = modulus; + as_neg.sub_with_borrow(&value); + + // The smaller of value and it's q's complement is the absolute + // value. + let mut abs_value = BigInt::min(value, as_neg); + + // To make a positive number negative in 2's complement, + // subtract 1 and flip the bits. So, here we sub 1 from abs if + // original value was negative. + let big_negative = BigInt::from(is_negative as u8); + abs_value.sub_with_borrow(&big_negative); + + for i in 0..(log_b - 1) { + let bit = abs_value.get_bit(i as usize); + + // Invert the bit if the original value was negative + bitvec.push(bit ^ is_negative); + } + + // Now push the sign bit + bitvec.push(is_negative); + } + /** * Takes a slice of values in a field `Zq`, treats the values as signed [q's * complement](https://en.wikipedia.org/wiki/Method_of_complements) * and converts the value to binary 2's complement. * * `value` is the element in Zq and `b` is the number of bits needed - * to represent the + * to represent the signed value. */ fn to_2s_complement( values: &[Fp, N>], @@ -852,36 +903,7 @@ impl LogProof { // This code should not feature timing side-channels. for value in values.iter() { - // Get the value out of Montgomery form. - let value = MontBackend::into_bigint(*value); - - let mod_div_2 = Fp::, N>::field_modulus_div_2(); - let modulus = Fp::, N>::field_modulus(); - let is_negative = value > mod_div_2; - - // Compute the q's complement of value - let mut as_neg: BigInt = modulus; - as_neg.sub_with_borrow(&value); - - // The smaller of value and it's q's complement is the absolute - // value. - let mut abs_value = BigInt::min(value, as_neg); - - // To make a positive number negative in 2's complement, - // subtract 1 and flip the bits. So, here we sub 1 from abs if - // original value was negative. - let big_negative = BigInt::from(is_negative as u8); - abs_value.sub_with_borrow(&big_negative); - - for i in 0..(log_b - 1) { - let bit = abs_value.get_bit(i as usize); - - // Invert the bit if the original value was negative - bitvec.push(bit ^ is_negative); - } - - // Now push the sign bit - bitvec.push(is_negative); + LogProof::to_2s_complement_single(value, log_b, &mut bitvec); } bitvec