Browse Source

Add versions of the scalarmul gadget that don't take an accumulator

Ian Goldberg 4 years ago
parent
commit
a145003c92
3 changed files with 111 additions and 30 deletions
  1. 107 7
      ecgadget.hpp
  2. 1 2
      pedersen.cpp
  3. 3 21
      scalarmul.cpp

+ 107 - 7
ecgadget.hpp

@@ -56,7 +56,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     lambda.allocate(this->pb, "lambda");
     inxsq.allocate(this->pb, "inxsq");
   }
@@ -109,7 +109,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     lambda.allocate(this->pb, "lambda");
   }
 
@@ -157,7 +157,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     lambda.allocate(this->pb, "lambda");
   }
 
@@ -211,7 +211,7 @@ public:
     P0x(P0x), P0y(P0y), P1x(P1x), P1y(P1y)
   {
     // Allocate variables to protoboard
-	  
+
     addx.assign(pb, which * (P1x-P0x) + P0x);
     addy.assign(pb, which * (P1y-P0y) + P0y);
     adder.emplace_back(this->pb, outx, outy, inx, iny, addx, addy);
@@ -262,7 +262,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     lambda.allocate(this->pb, "lambda");
     sumx.allocate(this->pb, "sumx");
     sumy.allocate(this->pb, "sumy");
@@ -432,7 +432,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     size_t numbits = FieldT::num_bits;
     svec.allocate(this->pb, numbits, "svec");
     packers.emplace_back(this->pb, svec, s);
@@ -452,6 +452,106 @@ public:
   }
 };
 
+// Compute s*P as (outx, outy) for a given constant point P, and s given
+// as a bit vector.  The _caller_ is responsible for proving that the
+// elements of svec are bits.
+template<typename FieldT>
+class ec_constant_scalarmul_vec_gadget : public gadget<FieldT> {
+private:
+  FieldT Cx, Cy, Ax, Ay, AXSx, AXSy;
+  pb_variable<FieldT> accinx, acciny, accoutx, accouty;
+  std::vector<ec_constant_scalarmul_vec_accum_gadget<FieldT> > scalarmuls;
+  std::vector<ec_constant_add_gadget<FieldT> > adders;
+public:
+  const pb_variable<FieldT> outx, outy;
+  const pb_variable_array<FieldT> svec;
+  const FieldT Px, Py;
+
+  ec_constant_scalarmul_vec_gadget(protoboard<FieldT> &pb,
+              const pb_variable<FieldT> &outx,
+              const pb_variable<FieldT> &outy,
+              const pb_variable_array<FieldT> &svec,
+              const FieldT &Px, const FieldT &Py) :
+    gadget<FieldT>(pb, "ec_constant_scalarmul_vec_gadget"),
+    // Precomputed coordinates of C and A
+    Cx(2),
+    Cy("4950745124018817972378217179409499695353526031437053848725554590521829916331"),
+    Ax("7536839002660211356286040193441766649532044555061394833845553337792579131020"),
+    Ay("11391058648720923807988142436733355540810929560298907319389650598553246451302"),
+    outx(outx), outy(outy), svec(svec), Px(Px), Py(Py)
+  {
+    AXSx = Ax;
+    AXSy = Ay;
+    accinx.allocate(this->pb, "accinx");
+    acciny.allocate(this->pb, "acciny");
+    accoutx.allocate(this->pb, "accoutx");
+    accouty.allocate(this->pb, "accouty");
+
+    scalarmuls.emplace_back(pb, accoutx, accouty, accinx, acciny, svec, Px, Py, AXSx, AXSy);
+    adders.emplace_back(pb, outx, outy, accoutx, accouty, AXSx, -AXSy);
+  }
+
+  void generate_r1cs_constraints()
+  {
+    this->pb.add_r1cs_constraint(r1cs_constraint<FieldT>(accinx, 1, Ax));
+    this->pb.add_r1cs_constraint(r1cs_constraint<FieldT>(acciny, 1, Ay));
+    scalarmuls[0].generate_r1cs_constraints();
+    adders[0].generate_r1cs_constraints();
+  }
+
+  void generate_r1cs_witness()
+  {
+    this->pb.val(accinx) = Ax;
+    this->pb.val(acciny) = Ay;
+    scalarmuls[0].generate_r1cs_witness();
+    adders[0].generate_r1cs_witness();
+  }
+};
+
+// Compute s*P as (outx, outy) for a given constant point P, and s given
+// as a field element.
+template<typename FieldT>
+class ec_constant_scalarmul_gadget : public gadget<FieldT> {
+private:
+  pb_variable_array<FieldT> svec;
+  std::vector<packing_gadget<FieldT> > packers;
+  std::vector<ec_constant_scalarmul_vec_gadget<FieldT> > vecgadget;
+
+public:
+  const pb_variable<FieldT> outx, outy;
+  const pb_variable<FieldT> s;
+  const FieldT Px, Py;
+
+  ec_constant_scalarmul_gadget(protoboard<FieldT> &pb,
+              const pb_variable<FieldT> &outx,
+              const pb_variable<FieldT> &outy,
+              const pb_variable<FieldT> &s,
+              const FieldT &Px, const FieldT &Py) :
+    gadget<FieldT>(pb, "ec_constant_scalarmul_gadget"),
+    outx(outx), outy(outy), s(s), Px(Px), Py(Py)
+  {
+    // Allocate variables to protoboard
+    // The strings (like "x") are only for debugging purposes
+
+    size_t numbits = FieldT::num_bits;
+    svec.allocate(this->pb, numbits, "svec");
+    packers.emplace_back(this->pb, svec, s);
+    vecgadget.emplace_back(this->pb, outx, outy, svec, Px, Py);
+  }
+
+  void generate_r1cs_constraints()
+  {
+    packers[0].generate_r1cs_constraints(true);
+    vecgadget[0].generate_r1cs_constraints();
+  }
+
+  void generate_r1cs_witness()
+  {
+    packers[0].generate_r1cs_witness_from_packed();
+    vecgadget[0].generate_r1cs_witness();
+  }
+};
+
 // Compute a*G + b*H as (outx, outy), given a and b as field elements.
 template<typename FieldT>
 class ec_pedersen_gadget : public gadget<FieldT> {
@@ -481,7 +581,7 @@ public:
   {
     // Allocate variables to protoboard
     // The strings (like "x") are only for debugging purposes
-	  
+
     accinx.allocate(this->pb, "accinx");
     acciny.allocate(this->pb, "acciny");
     accmidx.allocate(this->pb, "accmidx");

+ 1 - 2
pedersen.cpp

@@ -38,8 +38,7 @@ int main()
 
   pb.set_input_sizes(2);
 
-  // Initialize gadget
-
+  // Initialize the gadget
   ec_pedersen_gadget<FieldT> ped(pb, outx, outy, a, b);
   ped.generate_r1cs_constraints();
   

+ 3 - 21
scalarmul.cpp

@@ -24,15 +24,9 @@ int main()
 
   protoboard<FieldT> pb;
   pb_variable<FieldT> outx, outy;
-  pb_variable<FieldT> accinx, acciny, accoutx, accouty;
   pb_variable<FieldT> s;
 
-  // An accumulator initial value.  Its DL representation with respect
-  // to C and P should be unknown.
-  const FieldT Ax = FieldT("7536839002660211356286040193441766649532044555061394833845553337792579131020");
-  const FieldT Ay = FieldT("11391058648720923807988142436733355540810929560298907319389650598553246451302");
-  FieldT AXSx = Ax;
-  FieldT AXSy = Ay;
+  // The constant base point P
   const FieldT Px = FieldT(0);
   const FieldT Py = FieldT("11977228949870389393715360594190192321220966033310912010610740966317727761886");
 
@@ -40,10 +34,6 @@ int main()
 
   outx.allocate(pb, "outx");
   outy.allocate(pb, "outy");
-  accinx.allocate(pb, "accinx");
-  acciny.allocate(pb, "acciny");
-  accoutx.allocate(pb, "accoutx");
-  accouty.allocate(pb, "accouty");
   s.allocate(pb, "s");
 
   // This sets up the protoboard variables so that the first n of them
@@ -51,14 +41,9 @@ int main()
 
   pb.set_input_sizes(2);
 
-  // Initialize the accumulator
-  pb.add_r1cs_constraint(r1cs_constraint<FieldT>(accinx, 1, Ax));
-  pb.add_r1cs_constraint(r1cs_constraint<FieldT>(acciny, 1, Ay));
   // Initialize the gadget
-  ec_constant_scalarmul_accum_gadget<FieldT> sm(pb, accoutx, accouty, accinx, acciny, s, Px, Py, AXSx, AXSy);
+  ec_constant_scalarmul_gadget<FieldT> sm(pb, outx, outy, s, Px, Py);
   sm.generate_r1cs_constraints();
-  // Subtract the accumulator excess to get the result
-  ec_constant_add_gadget<FieldT> ad(pb, outx, outy, accoutx, accouty, AXSx, -AXSy);
 
   const r1cs_constraint_system<FieldT> constraint_system = pb.get_constraint_system();
 
@@ -68,13 +53,10 @@ int main()
 
   cout << "Prover" << endl;
   
-  pb.val(accinx) = Ax;
-  pb.val(acciny) = Ay;
   pb.val(s) = FieldT::random_element();
   cout << "Computing " << pb.val(s) << "*G" << endl;
 
   sm.generate_r1cs_witness();
-  ad.generate_r1cs_witness();
 
   const r1cs_gg_ppzksnark_proof<default_r1cs_gg_ppzksnark_pp> proof = r1cs_gg_ppzksnark_prover<default_r1cs_gg_ppzksnark_pp>(keypair.pk, pb.primary_input(), pb.auxiliary_input());
 
@@ -85,7 +67,7 @@ int main()
   cout << "Number of R1CS constraints: " << constraint_system.num_constraints() << endl;
   cout << "Primary (public) input: " << pb.primary_input() << endl;
   cout << "Auxiliary (private) input length: " << pb.auxiliary_input().size() << endl;
-  //cout << "Auxiliary (private) input: " << pb.auxiliary_input() << endl;
+//  cout << "Auxiliary (private) input: " << pb.auxiliary_input() << endl;
   cout << "Verification status: " << verified << endl;
 
   ofstream pkfile("pk_scalarmul");