Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
merkle_path_selector.tcc
Go to the documentation of this file.
1 // DISCLAIMER:
2 // Content taken and adapted from:
3 // https://github.com/HarryR/ethsnarks/blob/master/src/gadgets/merkle_tree.hpp
4 // https://github.com/HarryR/ethsnarks/blob/master/src/gadgets/merkle_tree.cpp
5 
6 #ifndef __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__
7 #define __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__
8 
9 namespace libzeth
10 {
11 
12 template<typename FieldT>
13 merkle_path_selector<FieldT>::merkle_path_selector(
14  libsnark::protoboard<FieldT> &pb,
15  const libsnark::pb_variable<FieldT> &input,
16  const libsnark::pb_variable<FieldT> &pathvar,
17  const libsnark::pb_variable<FieldT> &is_right,
18  const std::string &annotation_prefix)
19  : libsnark::gadget<FieldT>(pb, annotation_prefix)
20  , input(input)
21  , pathvar(pathvar)
22  , is_right(is_right)
23 {
24  // We allocate the selector's outputs left and right
25  left.allocate(pb, FMT(this->annotation_prefix, " left"));
26  right.allocate(pb, FMT(this->annotation_prefix, " right"));
27 };
28 
29 template<typename FieldT>
30 void merkle_path_selector<FieldT>::generate_r1cs_constraints()
31 {
32  // Constrain is_right to be boolean
33  this->pb.add_r1cs_constraint(
34  libsnark::r1cs_constraint<FieldT>(is_right, 1 - is_right, 0),
35  FMT(this->annotation_prefix, " is_right"));
36 
37  // We then constrain left to be the authentication node if is_right = 1,
38  // input otherwise
39  this->pb.add_r1cs_constraint(
40  libsnark::r1cs_constraint<FieldT>(
41  is_right, pathvar - input, left - input),
42  FMT(this->annotation_prefix,
43  " is_right*pathvar+(1-is_right)*input=left"));
44 
45  // Inversely, we constrain right to be the input if is_right = 1, the
46  // authentication node otherwise
47  this->pb.add_r1cs_constraint(
48  libsnark::r1cs_constraint<FieldT>(
49  is_right, input - pathvar, right - pathvar),
50  FMT(this->annotation_prefix,
51  " is_right*input+(1-is_right)*pathvar=right"));
52 };
53 
54 template<typename FieldT>
55 void merkle_path_selector<FieldT>::generate_r1cs_witness()
56 {
57  // We compute left and right according to the constrains
58  this->pb.val(left) =
59  this->pb.val(input) +
60  this->pb.val(is_right) * (this->pb.val(pathvar) - this->pb.val(input));
61  this->pb.val(right) =
62  this->pb.val(pathvar) +
63  this->pb.val(is_right) * (this->pb.val(input) - this->pb.val(pathvar));
64 };
65 
66 template<typename FieldT>
67 const libsnark::pb_variable<FieldT> &merkle_path_selector<FieldT>::get_left()
68 {
69  return left;
70 };
71 
72 template<typename FieldT>
73 const libsnark::pb_variable<FieldT> &merkle_path_selector<FieldT>::get_right()
74 {
75  return right;
76 };
77 
78 } // namespace libzeth
79 
80 #endif // __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__