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
 
    6 #ifndef __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__
 
    7 #define __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__
 
   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)
 
   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"));
 
   29 template<typename FieldT>
 
   30 void merkle_path_selector<FieldT>::generate_r1cs_constraints()
 
   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"));
 
   37     // We then constrain left to be the authentication node if is_right = 1,
 
   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"));
 
   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"));
 
   54 template<typename FieldT>
 
   55 void merkle_path_selector<FieldT>::generate_r1cs_witness()
 
   57     // We compute left and right according to the constrains
 
   60         this->pb.val(is_right) * (this->pb.val(pathvar) - this->pb.val(input));
 
   62         this->pb.val(pathvar) +
 
   63         this->pb.val(is_right) * (this->pb.val(input) - this->pb.val(pathvar));
 
   66 template<typename FieldT>
 
   67 const libsnark::pb_variable<FieldT> &merkle_path_selector<FieldT>::get_left()
 
   72 template<typename FieldT>
 
   73 const libsnark::pb_variable<FieldT> &merkle_path_selector<FieldT>::get_right()
 
   78 } // namespace libzeth
 
   80 #endif // __ZETH_CIRCUITS_MERKLE_PATH_SELECTOR_TCC__