template class merkle_tree_gadget : gadget { private: typedef sha256_two_to_one_hash_gadget sha256_gadget; pb_variable_array positions; std::shared_ptr> authvars; std::shared_ptr> auth; public: merkle_tree_gadget( protoboard& pb, digest_variable leaf, digest_variable root, pb_variable& enforce ) : gadget(pb) { positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH); authvars.reset(new merkle_authentication_path_variable( pb, INCREMENTAL_MERKLE_TREE_DEPTH, "auth" )); auth.reset(new merkle_tree_check_read_gadget( pb, INCREMENTAL_MERKLE_TREE_DEPTH, positions, leaf, root, *authvars, enforce, "" )); } void generate_r1cs_constraints() { for (size_t i = 0; i < INCREMENTAL_MERKLE_TREE_DEPTH; i++) { // TODO: This might not be necessary, and doesn't // appear to be done in libsnark's tests, but there // is no documentation, so let's do it anyway to // be safe. generate_boolean_r1cs_constraint( this->pb, positions[i], "boolean_positions" ); } authvars->generate_r1cs_constraints(); auth->generate_r1cs_constraints(); } void generate_r1cs_witness(const MerklePath& path) { // TODO: Change libsnark so that it doesn't require this goofy // number thing in its API. size_t path_index = convertVectorToInt(path.index); positions.fill_with_bits_of_uint64(this->pb, path_index); authvars->generate_r1cs_witness(path_index, path.authentication_path); auth->generate_r1cs_witness(); } };