You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
4.0 KiB

  1. use crate::prelude::*;
  2. use ark_ff::Field;
  3. use ark_relations::r1cs::SynthesisError;
  4. use ark_std::vec::Vec;
  5. /// Generates constraints for selecting between one of two values.
  6. pub trait CondSelectGadget<ConstraintF: Field>
  7. where
  8. Self: Sized,
  9. Self: Clone,
  10. {
  11. /// If `cond == &Boolean::TRUE`, then this returns `true_value`; else,
  12. /// returns `false_value`.
  13. ///
  14. /// # Note
  15. /// `Self::conditionally_select(cond, true_value, false_value)?` can be more
  16. /// succinctly written as `cond.select(&true_value, &false_value)?`.
  17. fn conditionally_select(
  18. cond: &Boolean<ConstraintF>,
  19. true_value: &Self,
  20. false_value: &Self,
  21. ) -> Result<Self, SynthesisError>;
  22. /// Returns an element of `values` whose index in represented by `position`.
  23. /// `position` is an array of boolean that represents an unsigned integer in big endian order.
  24. ///
  25. /// # Example
  26. /// To get the 6th element of `values`, convert unsigned integer 6 (`0b110`) to `position = [True, True, False]`,
  27. /// and call `conditionally_select_power_of_two_vector(position, values)`.
  28. fn conditionally_select_power_of_two_vector(
  29. position: &[Boolean<ConstraintF>],
  30. values: &[Self],
  31. ) -> Result<Self, SynthesisError> {
  32. let m = values.len();
  33. let n = position.len();
  34. // Assert m is a power of 2, and n = log(m)
  35. assert!(m.is_power_of_two());
  36. assert_eq!(1 << n, m);
  37. let mut cur_mux_values = values.to_vec();
  38. // Traverse the evaluation tree from bottom to top in level order traversal.
  39. // This is method 5.1 from https://github.com/mir-protocol/r1cs-workshop/blob/master/workshop.pdf
  40. // TODO: Add method 5.2/5.3
  41. for i in 0..n {
  42. // Size of current layer.
  43. let cur_size = 1 << (n - i);
  44. assert_eq!(cur_mux_values.len(), cur_size);
  45. let mut next_mux_values = Vec::new();
  46. for j in (0..cur_size).step_by(2) {
  47. let cur = Self::conditionally_select(
  48. &position[n - 1 - i],
  49. // true case
  50. &cur_mux_values[j + 1],
  51. // false case
  52. &cur_mux_values[j],
  53. )?;
  54. next_mux_values.push(cur);
  55. }
  56. cur_mux_values = next_mux_values;
  57. }
  58. Ok(cur_mux_values[0].clone())
  59. }
  60. }
  61. /// Performs a lookup in a 4-element table using two bits.
  62. pub trait TwoBitLookupGadget<ConstraintF: Field>
  63. where
  64. Self: Sized,
  65. {
  66. /// The type of values being looked up.
  67. type TableConstant;
  68. /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1]
  69. /// << 1)`, and then outputs `constants[b]`.
  70. ///
  71. /// For example, if `bits == [0, 1]`, and `constants == [0, 1, 2, 3]`, this
  72. /// method should output a variable corresponding to `2`.
  73. ///
  74. /// # Panics
  75. ///
  76. /// This method panics if `bits.len() != 2` or `constants.len() != 4`.
  77. fn two_bit_lookup(
  78. bits: &[Boolean<ConstraintF>],
  79. constants: &[Self::TableConstant],
  80. ) -> Result<Self, SynthesisError>;
  81. }
  82. /// Uses three bits to perform a lookup into a table, where the last bit
  83. /// conditionally negates the looked-up value.
  84. pub trait ThreeBitCondNegLookupGadget<ConstraintF: Field>
  85. where
  86. Self: Sized,
  87. {
  88. /// The type of values being looked up.
  89. type TableConstant;
  90. /// Interprets the slice `bits` as a two-bit integer `b = bits[0] + (bits[1]
  91. /// << 1)`, and then outputs `constants[b] * c`, where `c = if bits[2] {
  92. /// -1 } else { 1 };`.
  93. ///
  94. /// That is, `bits[2]` conditionally negates the looked-up value.
  95. ///
  96. /// For example, if `bits == [1, 0, 1]`, and `constants == [0, 1, 2, 3]`,
  97. /// this method should output a variable corresponding to `-1`.
  98. ///
  99. /// # Panics
  100. ///
  101. /// This method panics if `bits.len() != 3` or `constants.len() != 4`.
  102. fn three_bit_cond_neg_lookup(
  103. bits: &[Boolean<ConstraintF>],
  104. b0b1: &Boolean<ConstraintF>,
  105. constants: &[Self::TableConstant],
  106. ) -> Result<Self, SynthesisError>;
  107. }