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.

229 lines
6.5 KiB

  1. use bellperson::{
  2. gadgets::{boolean::AllocatedBit, num::AllocatedNum},
  3. ConstraintSystem, SynthesisError,
  4. };
  5. use ff::{PrimeField, PrimeFieldBits};
  6. use nova_snark::{gadgets::ecc::AllocatedPoint, traits::circuit::StepCircuit};
  7. use subtle::Choice;
  8. // An affine point coordinate that is on the curve.
  9. #[derive(Clone, Copy, Debug)]
  10. pub struct Coordinate<F>
  11. where
  12. F: PrimeField<Repr = [u8; 32]>,
  13. {
  14. pub x: F,
  15. pub y: F,
  16. pub is_infinity: bool,
  17. }
  18. impl<F> Coordinate<F>
  19. where
  20. F: PrimeField<Repr = [u8; 32]>,
  21. {
  22. // New affine point coordiante on the curve so is_infinity = false.
  23. pub fn new(x: F, y: F) -> Self {
  24. Self {
  25. x,
  26. y,
  27. is_infinity: false,
  28. }
  29. }
  30. }
  31. // An ECDSA signature
  32. #[derive(Clone, Debug)]
  33. pub struct EcdsaSignature<Fb, Fs>
  34. where
  35. Fb: PrimeField<Repr = [u8; 32]>,
  36. Fs: PrimeField<Repr = [u8; 32]> + PrimeFieldBits,
  37. {
  38. pk: Coordinate<Fb>, // public key
  39. r: Coordinate<Fb>, // (r, s) is the ECDSA signature
  40. s: Fs,
  41. c: Fs, // hash of the message
  42. g: Coordinate<Fb>, // generator of the group; could be omitted if Nova's traits allow accessing the generator
  43. }
  44. impl<Fb, Fs> EcdsaSignature<Fb, Fs>
  45. where
  46. Fb: PrimeField<Repr = [u8; 32]>,
  47. Fs: PrimeField<Repr = [u8; 32]> + PrimeFieldBits,
  48. {
  49. pub fn new(pk: Coordinate<Fb>, r: Coordinate<Fb>, s: Fs, c: Fs, g: Coordinate<Fb>) -> Self {
  50. Self { pk, r, s, c, g }
  51. }
  52. }
  53. // An ECDSA signature proof that we will use on the primary curve
  54. #[derive(Clone, Debug)]
  55. pub struct EcdsaCircuit<F>
  56. where
  57. F: PrimeField<Repr = [u8; 32]>,
  58. {
  59. pub r: Coordinate<F>,
  60. pub g: Coordinate<F>,
  61. pub pk: Coordinate<F>,
  62. pub c: F,
  63. pub s: F,
  64. pub c_bits: Vec<Choice>,
  65. pub s_bits: Vec<Choice>,
  66. }
  67. impl<F> EcdsaCircuit<F>
  68. where
  69. F: PrimeField<Repr = [u8; 32]>,
  70. {
  71. // Creates a new [`EcdsaCircuit<Fb, Fs>`]. The base and scalar field elements from the curve
  72. // field used by the signature are converted to scalar field elements from the cyclic curve
  73. // field used by the circuit.
  74. pub fn new<Fb, Fs>(num_steps: usize, signatures: &[EcdsaSignature<Fb, Fs>]) -> (Vec<F>, Vec<Self>)
  75. where
  76. Fb: PrimeField<Repr = [u8; 32]>,
  77. Fs: PrimeField<Repr = [u8; 32]> + PrimeFieldBits,
  78. {
  79. let mut z0 = Vec::new();
  80. let mut circuits = Vec::new();
  81. for (i, signature) in signatures.iter().enumerate().take(num_steps) {
  82. let r = Coordinate::new(
  83. F::from_repr(signature.r.x.to_repr()).unwrap(),
  84. F::from_repr(signature.r.y.to_repr()).unwrap(),
  85. );
  86. let g = Coordinate::new(
  87. F::from_repr(signature.g.x.to_repr()).unwrap(),
  88. F::from_repr(signature.g.y.to_repr()).unwrap(),
  89. );
  90. let pk = Coordinate::new(
  91. F::from_repr(signature.pk.x.to_repr()).unwrap(),
  92. F::from_repr(signature.pk.y.to_repr()).unwrap(),
  93. );
  94. let c_bits = Self::to_le_bits(&signature.c);
  95. let s_bits = Self::to_le_bits(&signature.s);
  96. let c = F::from_repr(signature.c.to_repr()).unwrap();
  97. let s = F::from_repr(signature.s.to_repr()).unwrap();
  98. let circuit = EcdsaCircuit {
  99. r,
  100. g,
  101. pk,
  102. c,
  103. s,
  104. c_bits,
  105. s_bits,
  106. };
  107. circuits.push(circuit);
  108. if i == 0 {
  109. z0 = vec![r.x, r.y, g.x, g.y, pk.x, pk.y, c, s];
  110. }
  111. }
  112. (z0, circuits)
  113. }
  114. // Converts the scalar field element from the curve used by the signature to a bit represenation
  115. // for later use in scalar multiplication using the cyclic curve used by the circuit.
  116. fn to_le_bits<Fs>(fs: &Fs) -> Vec<Choice>
  117. where
  118. Fs: PrimeField<Repr = [u8; 32]> + PrimeFieldBits,
  119. {
  120. let bits = fs
  121. .to_repr()
  122. .iter()
  123. .flat_map(|byte| (0..8).map(move |i| Choice::from((byte >> i) & 1u8)))
  124. .collect::<Vec<Choice>>();
  125. bits
  126. }
  127. // Synthesize a bit representation into circuit gadgets.
  128. fn synthesize_bits<CS: ConstraintSystem<F>>(
  129. cs: &mut CS,
  130. bits: &[Choice],
  131. ) -> Result<Vec<AllocatedBit>, SynthesisError> {
  132. let alloc_bits: Vec<AllocatedBit> = bits
  133. .iter()
  134. .enumerate()
  135. .map(|(i, bit)| {
  136. AllocatedBit::alloc(
  137. cs.namespace(|| format!("bit {}", i)),
  138. Some(bit.unwrap_u8() == 1u8),
  139. )
  140. })
  141. .collect::<Result<Vec<AllocatedBit>, SynthesisError>>()
  142. .unwrap();
  143. Ok(alloc_bits)
  144. }
  145. }
  146. impl<F> StepCircuit<F> for EcdsaCircuit<F>
  147. where
  148. F: PrimeField<Repr = [u8; 32]> + PrimeFieldBits,
  149. {
  150. fn arity(&self) -> usize {
  151. 8
  152. }
  153. // Prove knowledge of the sk used to generate the Ecdsa signature (R,s)
  154. // with public key PK and message commitment c.
  155. // [s]G == R + [c]PK
  156. fn synthesize<CS: ConstraintSystem<F>>(
  157. &self,
  158. cs: &mut CS,
  159. _z: &[AllocatedNum<F>],
  160. ) -> Result<Vec<AllocatedNum<F>>, SynthesisError> {
  161. let g = AllocatedPoint::alloc(
  162. cs.namespace(|| "G"),
  163. Some((self.g.x, self.g.y, self.g.is_infinity)),
  164. )?;
  165. let s_bits = Self::synthesize_bits(&mut cs.namespace(|| "s_bits"), &self.s_bits)?;
  166. let sg = g.scalar_mul(cs.namespace(|| "[s]G"), s_bits)?;
  167. let r = AllocatedPoint::alloc(
  168. cs.namespace(|| "R"),
  169. Some((self.r.x, self.r.y, self.r.is_infinity)),
  170. )?;
  171. let c_bits = Self::synthesize_bits(&mut cs.namespace(|| "c_bits"), &self.c_bits)?;
  172. let pk = AllocatedPoint::alloc(
  173. cs.namespace(|| "PK"),
  174. Some((self.pk.x, self.pk.y, self.pk.is_infinity)),
  175. )?;
  176. let cpk = pk.scalar_mul(&mut cs.namespace(|| "[c]PK"), c_bits)?;
  177. let rcpk = cpk.add(&mut cs.namespace(|| "R + [c]PK"), &r)?;
  178. let (rcpk_x, rcpk_y, _) = rcpk.get_coordinates();
  179. let (sg_x, sg_y, _) = sg.get_coordinates();
  180. cs.enforce(
  181. || "sg_x == rcpk_x",
  182. |lc| lc + sg_x.get_variable(),
  183. |lc| lc + CS::one(),
  184. |lc| lc + rcpk_x.get_variable(),
  185. );
  186. cs.enforce(
  187. || "sg_y == rcpk_y",
  188. |lc| lc + sg_y.get_variable(),
  189. |lc| lc + CS::one(),
  190. |lc| lc + rcpk_y.get_variable(),
  191. );
  192. let rx = AllocatedNum::alloc(cs.namespace(|| "rx"), || Ok(self.r.x))?;
  193. let ry = AllocatedNum::alloc(cs.namespace(|| "ry"), || Ok(self.r.y))?;
  194. let gx = AllocatedNum::alloc(cs.namespace(|| "gx"), || Ok(self.g.x))?;
  195. let gy = AllocatedNum::alloc(cs.namespace(|| "gy"), || Ok(self.g.y))?;
  196. let pkx = AllocatedNum::alloc(cs.namespace(|| "pkx"), || Ok(self.pk.x))?;
  197. let pky = AllocatedNum::alloc(cs.namespace(|| "pky"), || Ok(self.pk.y))?;
  198. let c = AllocatedNum::alloc(cs.namespace(|| "c"), || Ok(self.c))?;
  199. let s = AllocatedNum::alloc(cs.namespace(|| "s"), || Ok(self.s))?;
  200. Ok(vec![rx, ry, gx, gy, pkx, pky, c, s])
  201. }
  202. fn output(&self, _z: &[F]) -> Vec<F> {
  203. vec![
  204. self.r.x, self.r.y, self.g.x, self.g.y, self.pk.x, self.pk.y, self.c, self.s,
  205. ]
  206. }
  207. }