Browse Source

Handle const * Term and const * Pedersen in the Pedersen recognizer

Ian Goldberg 4 months ago
parent
commit
edf24392d8
1 changed files with 64 additions and 0 deletions
  1. 64 0
      sigma_compiler_core/src/pedersen.rs

+ 64 - 0
sigma_compiler_core/src/pedersen.rs

@@ -304,6 +304,14 @@ impl Term {
             ..self
         })
     }
+
+    /// Multiply a [`Term`] by a constant
+    pub fn mul_const(self, arg: i128) -> Result<Self> {
+        Ok(Self {
+            coeff: self.coeff.mul_const(arg)?,
+            ..self
+        })
+    }
 }
 
 /// A representation of `(a*x+b)*A + (c*r+d)*B` where `a` and `c` are a
@@ -379,6 +387,14 @@ impl Pedersen {
             ))
         }
     }
+
+    /// Multiply a [`Pedersen`] by a constant
+    pub fn mul_const(self, arg: i128) -> Result<Self> {
+        Ok(Self {
+            var_term: self.var_term.mul_const(arg)?,
+            rand_term: self.rand_term.mul_const(arg)?,
+        })
+    }
 }
 
 /// Components of a Pedersen commitment
@@ -688,6 +704,26 @@ impl<'a> AExprFold<PedersenExpr> for RecognizeFold<'a> {
                 coeff: linscalar.mul_const(cval)?,
                 id,
             })),
+            // Multiplying a PubScalarExpr by a Term yields a Term if
+            // the PubScalarExpr is a constant
+            (
+                AExprType::Scalar {
+                    val: Some(const_val),
+                    ..
+                },
+                PedersenExpr::PubScalarExpr(_),
+                PedersenExpr::Term(term),
+            ) => Ok(PedersenExpr::Term(term.mul_const(const_val)?)),
+            // Multiplying a PubScalarExpr by a Pedersen yields a
+            // Pedersen if the PubScalarExpr is a constant
+            (
+                AExprType::Scalar {
+                    val: Some(const_val),
+                    ..
+                },
+                PedersenExpr::PubScalarExpr(_),
+                PedersenExpr::Pedersen(pedersen),
+            ) => Ok(PedersenExpr::Pedersen(pedersen.mul_const(const_val)?)),
             // Nothing else is valid
             _ => Err(Error::new(
                 proc_macro2::Span::call_site(),
@@ -1198,5 +1234,33 @@ mod test {
                 },
             }),
         );
+
+        recognize_tester(
+            vars,
+            randoms,
+            parse_quote! {
+                (3 * (2*x + a*b) * A + B * (3 * r - 7))* (7-2)
+            },
+            Some(Pedersen {
+                var_term: Term {
+                    coeff: LinScalar {
+                        coeff: 30,
+                        pub_scalar_expr: Some(parse_quote! { ((a * b) * 3i128) * 5i128 }),
+                        id: parse_quote! {x},
+                        is_vec: false,
+                    },
+                    id: parse_quote! {A},
+                },
+                rand_term: Term {
+                    coeff: LinScalar {
+                        coeff: 15,
+                        pub_scalar_expr: Some(parse_quote! { (-7i128) * 5i128 }),
+                        id: parse_quote! {r},
+                        is_vec: false,
+                    },
+                    id: parse_quote! {B},
+                },
+            }),
+        );
     }
 }