|
@@ -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");
|